Tcl 中的列表操作:
列表则是具有特殊解释的字符串。Tcl 中的列表操作和其它 Tcl 命令 一样具有相同的结构。
列表可应1用在诸如 foreach 这样的以列表为变元的循环命令中,也应于构建 eval 命令的延迟命令字符串。
一、list 命令
list 命令用来创建列表。 一个列表可以包含子列表,即列表可以嵌套。
>set l1 [list Sun Mon Tues]
=>Sun Mon Tues ; #列表 l1 含有三个元素
>set l2 [list $l1 Wed]
=> {Sun Mon Tues} Wed ; #列表 l2 中含有两个元素。第一个元素用花括号括起来。
>set b 10
>set l3 [list { a $b c} d]
=>{a $b c} d ;#花括号阻止引用替换
>set l3 [list "a $b c" d]
=> {a 10 c} d
在创建 list 的时候比较灵活,有时比较难以理解和容易出错,特别是花括号。如何理解花括号的作用呢?可以这么简单认为:花括号内部代表的是子列表。当用 list 命令创建列表的时 候,如果元素是单个的词,就不用大括弧括起来,但如果某个元素是以空格分割的字符串时, 就将其看作一个子列表而用花括号括起来。注意实际的处理过程并不是这样的,要复杂一些。
二、concat 命令
concat 命令以空格为分隔符将多个列表拼装在一起形成新的列表。
list 命令和 concat 命令都可以完成列表合并功能。list 命令保留每个列表的结构,将每个列表作为一个整体生成新列表的元素来完成。而 concat 命令则要先把各个列表的最外层列表结构去掉,将其中的所有元素取出来作为新列表的元素来完成合并,即新列表的每个元素也是合并前列表的元素。
>set x {1 2}
=> 1 2
>set y "$x {3}"
=>1 2 {3}
>set y [list $x {3}]
=>{1 2} 3; #list 命令保留了每个列表的结构
=>set y [concat $x {3}]
=>1 2 3
三、lappend 命令
lappend 命令用来将新元素追加到列表末尾。
>lappend new 1 2
=> 1 2
>lappend new {3 4} "5" {6} 7
=> 1 2 {3 4} 5 6 7
四、llength命令
llength 命令可以获得一个列表内元素的个数。
>set l1 "1 2 3 4 5"
=>1 2 3 4 5 ;#定义了一个字符串
>set num [llength $l1] ;#这里 l1 被看作列表了
=>5
这个例子中,先前定义的一个字符串被看作一个 list!(Tcl 中的 list 只不过是一个有特殊解 释的字符串)。 列表是用空格搁开的多个元素组成的字符串,而通过 list 相关命令得到了特殊解释。既然 list 是字符串,那么所有适用于字符串的操作命令也应该适用于列表。
五、lindex命令
lindex 命令返回列表中指定位置的特定元素。列表索引从 0 开始记数!
>set x {1 3 5}
=>1 3 5
>lindex $x 0
=>1
>lindex $x end
=>5
六、lrange命令
lrange 命令返回一个指定区段的列表元素,可以以 end 或者 end-n 作为索引(n 为正整 数)。
>lrange {1 2 3 {4 5} 6} 2 end
=> 3 {4 5} 6
七、linsert 和 lreplace 命令
linsert 命令用来将元素插入到一个列表的由索引指定的位置。如果索引为 0 或者更小,则元 素就会被添加到最前面。如果索引值大于或者等于列表长度,则元素被追加到列表尾部。其他 情况元素被添加到指定位置之前。
lreplace 命令将一个指定区段的列表元素替换为新元素。如果没有指定新元素,则这个区域 的元素就会被从列表中删除。
注意:这两个操作不会改变原来列表的内容,而是返回一个新列表。
>set x {1 2}
=>1 2
>set new [linsert $x 0 he she]
=>he she 1 2
>set new [linsert $x end he she]
=>1 2 he she
>lreplace $new 0 1 A B
=> A B he she
八、lsearch 命令
lsearch 命令在给定列表中搜索与匹配字符串匹配的元素,成功就返回正确的元素索引,否则返回-1。lsearch 支持通配符格式,但可以使用-exact 选项将其屏蔽而进行精确匹配。
>set l1 [list this is one list]
=>this is one list
>set index [lsearch $l1 l*]
=>3
>set index [lsearch -exact $l1 l*]
=>-1
九、lsort命令
lsort 命令实现对列表的排序。排序操作不影响原表,而是返回排序之后的新表。
排序的方式有多种选择,可以通过-ascii、-dictionary 、–integer、-real 来指定基本排序类 型,然后使用-increasing、decreasing 指定排列方式,默认为-ascii、-increasing 。要注意 ASCII 排序时使用字符编码;而 dictionary 排序方式整合大小写,并将包含的数字以数值大小来处理。
十、join与split命令
join 命令接收一个列表,并用指定的分隔符将列表元素整合成一个字符串
>join {1 {2 3} {4 5 6}} :
=> 1:2 3:4 5 6
split 命令的作用与 join 的作用相反,它接收一个字符串,并根据给定的字符将其分割转换成 一个列表。用于分割的字符应该在字符串中存在,否则 split 因为没有搜索到对应字符而将整个 字符串作为唯一列表元素而返回,即返回原字符串。
>set str cm8/auto/tools/aries/ASAM/NE/SNMP/IMPL/ne_create_board.tcl =>cm8/auto/tools/aries/ASAM/NE/SNMP/IMPL/ne_create_board.tcl
>set s /
=>/
>set l1 [split $str $s]
=> cm8 auto tools aries ASAM NE SNMP IMPL ne_create_board.tcl
>set l2 [split $str "/."] ;#可以指定多个分割符
=> cm8 auto tools aries ASAM NE SNMP IMPL ne_create_board tcl
split 的默认分割符为空白符,包括空格符、制表符和换行符。如果分割符在字符串开始位 置,或者有多个分割符相连,那么 split 命令就会产生空列表元素,并用{}表示,分割符并不被合并。
若打算将字符串的每个字符都区分开,即将每个字符都分割成列表元素,可以将分割符指定 为空字符串{},这个方法对分析和处理字符串中的每个字符时比较有用。当遇到字符串内含有特 殊的字符,如空格符时,split 也将其作为一个字符元素处理,为了利于区别起见,用花括号将 空格元素括起来。
>set str "/cm8 is a Vob directory, but /home/usr isn't one vob directory!"
=>/cm8 is a Vob directory, but /home/usr isn't one vob directory!
>set l3 [split $str "/ , ' !"]
=>{} cm8 is a Vob directory {} but {} home usr isn t one vob directory {}
>set l4 [split $str {}]
=>/ c m 8 { } i s { } a { } V o b { } d i r e c t o r y , { } b u t { } / h o m e / u s r { } i s n ' t { } o n e { } v o b { } d i r e c t o r y !
>set str "hello"
=>hello
>set l5 [split $str {}]
=>h e l l o
十一、foreach 控制结构
foreach 命令/控制结构会遍历整个列表,逐次取出列表的每个元素的值放到指定变量中, 使用者可以在跟随的过程体中添加必要的处理过程。
foreach 命令还可以同时对多个列表进行操作,而且还可以同时操作同一列表的多个元素。 如果在最后一次循环之前就遍历完了某个列表,则与之对应的循环变量就会以空字符串来赋值。
>foreach {x1 x2} {Orange Blue Red Green Black} x3 {Right Left Up Down} {
puts [format "x1=%8s x2=%8s x3=%8s" $x1 $x2 $x3]
}
=> x1= Orange x2= Blue x3= Right
x1= Red x2= Green x3= Left
x1= Black x2= x3= Up
x1= x2= x3= Down