0 回顧
列表part0和part1描述了列表的創建,修改,獲取,搜索等相關命令。接下來這篇文章將介紹列表的排序和拼接。通過這三篇文章的描述,詳細大家對列表具有一個詳細并且系統的認識。
1 排序
排序是一個老生常談的話題。最最最常見的排序方式就是升序,降序,unique以及字典等。下面將挨個介紹。
-
lsort命令格式
lsort <options> list0
該命令實現列表list0元素排序的功能。其中,option表示命令lsort包含的選項,一般以“-”開頭。常見的option包含:-decreasing,-increasing,-unique, -directionary(非常常用的一個選項),-integer,-real。 它們分別表示降序,升序,唯一,字典,整數(從小到大)和浮點數(從小到大);list0表示列表本身,而不是列表名稱。- decreasing表示列表中的元素從大到小排列
- increasing表示列表中的元素從小到大排列
- unique表示刪除隊列中重復的元素
- directionray表示按照字典(數字>小寫字母(a-z)>大寫字母(A-Z),其中數字從小到大,通常用于文件的排序)的方式對列表中的元素進行排序
- integer表示列表的元素按照從小到大的方式排列,排列的對象只能是整數
- real表示列表的元素按照從小到大的方式排列,排列的對象是浮點數或者整數。(整數1也可以認為是浮點數1.0)
-
基礎示例
# Example1 # 創建列表x_list0 set x_list0 [list John Anne Mary Jim] # 列表x_list0按照降序排列其中的元素 lsort -decreasing $x_list0 # 結果:Mary John Jim Anne# Example2 # 列表x_list0按照升序排列其中的元素 lsort -increasing $x_list0 # 結果: Anne Jim John Mary# Example3 # 創建列表x_lsit0 set x_list0 [list B a C 10 2] # 列表x_lsit0按照升序排列其中的元素 lsort -increasing $x_list0 # 結果: 10 2 B C a# Example4 # 創建列表x_list1 set x_lsit1 [list apple Banana Zebra 123] # 列表x_list1按照字典的方式排列其中的元素 lsort -dictionary $x_lsit1 # 結果:123 apple Banana# Example5 # 創建列表x_list1 set x_list1 [list n1.gif n10.gif n9.gif n11.gif] lsort -dictionary $x_lsit2 # 結果: n1.gif n9.gif n10.gif n11.gif# Example6 # 創建列表x_list2 set x_lsit2 [list apple Banana Zebra apple] # 刪除列表x_list2中重復的元素 lsort -unique $x_list2 # 結果:apple Banana Zebra# Example7 # 創建列表x_list3 set x_list3 [list 100 5 20] # 列表x_lsit3按照整數的方式從小到大 lsort -integer $x_list # 結果:5 20 100# Example8 # 創建隊列x_list4 set x_list4 [list 100 5.23 20.10] lsort -real $x_list4 # 結果: 5.23 20.10 100
-
解析
Example1~3展示了increasing和decreasing的基礎示例。其中,Example3混合了數字和字母,該實例是想說,increasing和decreasing排序每次比較一個字符的ASCII碼,若相同則比較下一個字符;直到兩者不同為止。字母和數字對應的ASCII碼如下所示:數字:0-9: 48-57 小寫字母:a-z: 65-90 大寫字母:A-Z: 97-122
這就很好的解釋了Example3中為啥“10”會排在“2”的前面。ASIC或者FPGA的follow中通常需要將多個文件進行排序,為此increasing和decreasing就顯得不那么友好,此時推薦使用dictionary。
Example8中100在排序時被當作100.0看待,即Tcl在排序前做了浮點類型的轉換。
2 拼接
- split命令格式
split str0 str1
該命令將字符串str0根據分隔符str1進行切分,并且返回一個列表。或者說,split命令會找到字符串str0中所有的分隔符,返回一個列表,列表中的元素就是分隔符str1之間的元素。其中,分隔符可以是空字符,單個字符或者多個字符;str0是字符串變量,而不是字符串的名字;str1可以是字符串,或者字符串變量。可以分成三種情況理解:
- 若分隔符str1是空字符, 則字符串str0的所有字符都被切分,即使是空格。即空格也會被分成一個單一的字符。
- 若分隔符str1是單個字符,則字符串str0將被分隔符str1進行切分;切分后的部分組成一個列表。
- 若分隔符str1是多個字符,則只要字符串str0中有一個字符和分隔符str1中的字符匹配,則字符串str0被切分一次;若連續兩個字符都和分隔符匹配(分隔符挨個匹配),則進行連續切分,獲得一個空字符;最終切分的元素返回一個列表。
-
基礎示例
# 創建字符串x_str0 set x_str0 xbaybz set x_str1 {} split $x_str0 $x_str1 # 結果:x b a y b z# 創建分隔符,并且分隔符是單個字符 set x_str1 b split $x_str0 $x_str1 # 結果:x ay z# 創建分隔符,并且分隔符多個字符 set x_str1 ab split a {} y z
-
解析
第一個實例中分隔符是空字符,因此,x_str0中的所有元素都將被切分。
第二個實例中分隔符是單個字符。字符串xbaybz將被分隔符b切分,切分后的部分組成一個列表,列表的元素為字符串切分后的各個部分。
第三個實例中分隔符是多個字符。字符串xbaybz將被分隔符ab切分。同學們看到這個結果可能會很意外。其實很簡單,我們把多個分隔符拆成多個單字符的分隔符就可以了。如本實例中,分隔符為“ab”,那咱們就看成兩個分隔符,分別為分隔符a和分隔符b。在切分過程中,字符串xbaybz同時和分隔符a,分隔符b進行匹配。只要其中一個匹配,則進行切分,隨后進入下一個字符的比較。詳細流程如下所示:
step1: 字符串中的第一個字符x和分隔符a進行匹配,發現不匹配;隨后進行字符x和分隔符b進行匹配,發現不匹配。進入step2;
step2: 字符b和分隔符a不匹配,隨即進行字符b和分隔符b進行匹配,此時匹配成功,進行切分。故列表的第1個元素是x。進入step3;
step3: 字符a和分隔符a進行匹配,匹配成功,進行切分。此時獲得一個空元素。故列表的第2個元素是一個空字符串。進入step4;
step4…
最終,列表的元素為: a {} y z。 -
join命令格式
join list0 str0
該命令可以理解為split命令的逆操作。將列表lsit0中的各個元素按照分隔字符串str0進行拼接,最終獲得一個字符串。其中,分隔字符串可以是任意多個字符串,包括空字符串。另外值得說明的是,list0和str0都是變量,而不是變量名稱。 -
基礎示例
# 創建列表x_list0 set x_list0 [list {} usr include sys types.h] # 創建分隔字符串 set split_str0 "/" join $x_list0 $split_str0 # 結果: /usr/include/sys/types.h# 創建列表x_list1 set x_list1 [list 24 112 5] # 創建分割字符串 set split_str1 "+" expr [join $x_list1 $split_str1] # 結果:141
-
解析
第一個實例實現了文件路徑的拼接,為了實現usr前面帶一個“/”,待拼接的列表x_list0需要包含一個空元素。即可以實現usr作為根目錄。
第二個實例實現列表數字的累計,是一個較為特殊的用法。該實例中,首先將列表的元素按照分割字符串“+”進行拼接;隨后將拼接好的字符串傳入expr;最后經過expr的計算,獲得最終的結果。