语法
lindex list ?index...?描述
lindex命令接受一个参数列表 list,可以接受0个或者多个 index参数,在多个参数的情况下,参数可以是单独的一次排列,也可以是在一个列表当中。如果不指定index参数:
lindex list或者
lindex list {}这种情况下返回 lindex列表本身。
当只有一个单独的元素时,lindex命令返回list列表中的第index个元素。替代时元素从0开始(也就是说索引0就是指列表的第一个元素),如果index是负数或者大于列表长度就返回一个空字符串。解释器在解释每一个index值时和string index命令相同,都支持单个和多个index参数。
如果指定了多个index,将会选择列表的子列表中的元素。例如
lindex $a 1 2 3或者
lindex $a {1 2 3}与下面的命令相同
lindex [lindex [lindex $a 1] 2] 3
示例
lindex {a b c} → a b c lindex {a b c} {} → a b c lindex {a b c} 0 → a lindex {a b c} 2 → c lindex {a b c} end → c lindex {a b c} end-1 → b lindex {{a b c} {d e f} {g h i}} 2 1 → h lindex {{a b c} {d e f} {g h i}} {2 1} → h lindex {{{a b} {c d}} {{e f} {g h}}} 1 1 0 → g lindex {{{a b} {c d}} {{e f} {g h}}} {1 1 0} → geval命令本身使用非常简单,但是用处非常大,如果需要动态的构造命令,那么必须使用eval命令。
foreach循环,格式为:
after有几种形式,使用比较灵活。
列表操作在脚本中使用的频率非常高,基本上每个脚本都会涉及到其中的一些操作,在这里对列表的命令进行实例解析,以加深对列表命令的理解,本文涉及的命令为list、concat、lrepeat、join和split。
使用重复的元素构建列表,number为重复的次数,element为重复的元素,这个命令就相当于对重复number次的element元素进行了list操作,所以lrepeat 1 arg ... 和list arg ... 执行结果相同。如下例:
% lrepeat 3 This is a tcltk example
This is a tcltk example This is a tcltk example This is a tcltk example
下例与list命令结果相同:
% lrepeat 1 This is a tcltk example
This is a tcltk example
两个嵌入式标志位:
列表操作在脚本中使用的频率非常高,基本上每个脚本都会涉及到其中的一些操作,在这里对列表的命令进行实例解析,以加深对列表命令的理解,本文涉及的命令为lappend、lreplace、lset、linsert、lsort和lreverse。
variable - 创建和初始化一个名字空间变量
语法
variable ? name value...? name ? value?描述
这个命令一般在名字空间中创建一个或多个变量,每个变量 name使用 value初始化,最后一个变量的 value是可选的。如果变量name不存在,就创建一个,在这种情况下,如果指定了value,就把它的值赋值给创建的变量,如果不指定value,新的变量name就没有初始化。如果变量已经存在,就赋值value,没有指定value则保持原来的值。一般来说name不做任何限定(不包含名字空间限定),并且在当前名字空间中创建,如果name包含有名字空间限定,变量就创建在指定的名字空间中,如果变量没有定义,对于namespace which命令来说就是可见的,但是对info exists命令来说是不可见的。
如果variable命令在一个tcl过程中执行,就创建一个局部变量,这个局部变量链接一个相关的名字空间变量(因此这些变量由info vars列出),这样variable命令类似global命令,虽然global命令只是链接一个在全局范围内的变量,如果给出了values,就用来修改相关名字空间变量,如果一个名字空间变量不存在,就创建一个并且初始化。
name变元不能引用一个数组的元素,但是name可以引用整个数组并且初始化的value必须符合数组的要求,声明过变量后,数组中的元素可以使用set和array命令来配置。
示例
在名字空间中创建一个变量:namespace eval foo { variable bar 12345 }
在名字空间中创建一个数组:
namespace eval someNS { variable someAry array set someAry { someName someValue otherName otherValue } }
为一个过程存取名字空间中的变量:
namespace eval foo { proc spong {} { # Variable in this namespace variable bar puts "bar is $bar" # Variable in another namespace variable ::someNS::someAry parray someAry } }array - 处理数组变量
语法
array option arrayName ?arg arg ...?
描述
这个命令执行几种可选项中的一个操作,操作的对象为arrayName,除非以下的命令特殊声明,否则arrayName必须是存在的数组变量名称。option变元决定了要对数组变量进行什么样的操作,具体如下:
- array anymore arrayName searchId
- 如果在一次数组搜索当中数组中还有剩余的元素就返回 1,如果没有剩余的元素就返回 0。 searchId指定了被检查 arrayName的搜索标示符,这个标示符必须是命令 array startsearch返回的搜索标示符。这个命令在数组有空索引的元素时非常有用,因为 array nextelement的返回值并不能说明搜索是否完毕。 array donesearch arrayName searchId
- 这个命令终结一次数组搜索, searchId指出了需要终结的数组搜索标示符,这个标示必须是命令 array startsearch返回的搜索标示符。返回一个空字符串。 array exists arrayName
- 如果 arrayName是一个数组变量就返回 1,如果没有这个变量或者是非数组变量就返回 0。 array get arrayName ?pattern?
- 返回一个列表,列表中的元素是成对的,交替的出现索引和对应数组值,如果不指定 pattern,所有数组的元素都回返回,如果指定了 pattern,只有匹配 pattern(与 string match匹配风格相同)的数组元素返回。如果 arrayName不是一个数组变量的名字或者没有包含任何元素就返回一个空列表。 array names arrayName ?mode? ?pattern?
- 返回一个匹配 pattern的数组元素索引的列表,mode可以是 -exact、 -glob或 -regexp中的一个,指定了匹配的风格,如果不指定 mode,默认为 -glob。如果需要了解详细的匹配风格请参考 string match和 regexp。如果不指定 pattern则返回数组中所有的索引,如果 arrayName不是一个数组变量的名字或者没有包含任何元素就返回一个空列表。 array nextelement arrayName searchId
- 返回 arrayName数组中的下一个元素索引,如果数组中所有的元素都搜索到了就返回空字符串, searchId指出了需要终结的数组搜索标示,这个标示必须是命令 array startsearch返回的搜索标示。警告:如果数组中有添加和删除元素的操作,那么所有的搜索都回自动结束,就像是调用了 array donesearch,这将会导致 array nextelement操作失败。 array set arrayName list
- 设置一个或多个数组元素, list必须是像 array get返回值风格的列表,第奇数个列表元素被认为是 arrayName的一个元素索引,紧接着的第偶数个列表元素就被当作前一个元素的数组中的值,如果变量 arrayName不存在或者为空,就创建一个空数组 arrayName。 array size arrayName
- 返回一个十进制的字符串数值来指出数组中元素的数量,如果 arrayName不是一个数组的名字就返回 0。 array startsearch arrayName
- 这个命令开始在 arrayName数组中进行一个元素一个元素的搜索, array nextelement命令返回下一元素的索引,当搜索完毕, array donesearch命令必须调用,返回值是一个搜索标示符,这个搜索表示符可以在 array nextelement和 array donesearch中使用来标示操作的搜索,通过使用搜索标示符允许对一个数组同时进行不同的搜索。目前,普遍使用的方式是使用 array get和 array names与 foreach一起使用来遍历数组中的每一个元素。具体请参考下面的示例。 array statistics arrayName
- 返回数组中元素在哈希表的分配方式的统计,这个命令包含表格中条目数,buckets数目和buckets的利用情况。 array unset arrayName ?pattern?
- 删除数组中所有匹配 pattern的元素(与 string match匹配风格相同),如果 arrayName不是一个数组变量或者没有匹配到任何元素,不会产生错误,如果忽略了 pattern变元并且 arrayName是一个数组名称,这个命令将删除整个数组所有的元素,这个命令总是返回一个空字符串。
示例
array set colorcount {
red 1
green 5
blue 4
white 9
} foreach {color count} [array get colorcount] {
puts "Color: $color Count: $count"
}
→ Color: blue Count: 4
Color: white Count: 9
Color: green Count: 5
Color: red Count: 1
foreach color [array names colorcount] {
puts "Color: $color Count: $colorcount($color)"
}
→ Color: blue Count: 4
Color: white Count: 9
Color: green Count: 5
Color: red Count: 1 foreach color [lsort [array names colorcount]] {
puts "Color: $color Count: $colorcount($color)"
}
→ Color: blue Count: 4
Color: green Count: 5
Color: red Count: 1
Color: white Count: 9 array statistics colorcount
→ 4 entries in table, 4 buckets
number of buckets with 0 entries: 1
number of buckets with 1 entries: 2
number of buckets with 2 entries: 1
number of buckets with 3 entries: 0
number of buckets with 4 entries: 0
number of buckets with 5 entries: 0
number of buckets with 6 entries: 0
number of buckets with 7 entries: 0
number of buckets with 8 entries: 0
number of buckets with 9 entries: 0
number of buckets with 10 or more entries: 0
average search distance for entry: 1.2
uplevel - 在不同的堆栈层中执行一个脚本
语法
uplevel ?level? arg ?arg ...?
描述
所有的arg变元使用concat命令风格连接起来,连接起来的命令在level指定后的作用域中执行,uplevel返回执行结果。(堆栈层可以看作是变量起作用的范围)
如果level是一个整数,它指出了调用命令的堆栈距离目前调用堆栈的层数,如果level是以#后面加一个数字,那么这个数字就是命令执行的绝对堆栈层,缺省值为1,如果有了#符号那么后面必须跟一个数字。
例如,假设过程a在最高层调用,然后a调用b,再后来b调用c,假设c调用uplevel名令,如果level是1或者#2或者忽略掉,这个命令将在b的变量的作用域中执行,如果level是2或者#1,那么这个命令将在a的变量的作用域中执行,如果level是3或者#0,这个命令将在最高层执行(只有全局变量是可见的)。
uplevel命令导致在调用过程的堆栈层中"看不到"过程了,在下面的例子里,假设c调用命令:
uplevel 1 {set x 43; d}当d是另外一个过程时,set命令会在b的作用域中修改变量x,d将在第三层堆栈运行,就像是b过程调用的d过程。
uplevel {set x 42}set命令将会修改在b作用域中的x变量,在执行d的时候过程c对于调用堆栈层是不可见的,命令info level可以获得当前程序的堆栈层。
uplevel可以实现新的控制结构,例如,uplevel可以实现while过程。
示例
uplevel命令在实现新的控制结构方面非常有用,下面的例子显示了它可以用来创建一个do命令:
proc do {body while condition} {
if {$while ne "while"} {
error "required word missing"
}
set conditionCmd [list expr $condition]
while {1} {
uplevel 1 $body
if {![uplevel 1 $conditionCmd]} {
break
}
}
}