书接上回,上次对TCL脚本语言做了初步的介绍,并对TCL的字符串相关指令操作做了详细的介绍,
链接: link
本文接着讲TCL语言的其余部分,包括:
列表
数组
控制结构
过程
这里写目录标题
一、列表
列表list是TCL中的基本数据结构,列表是元素的有序结合,这里的元素泛指各类项,例如字符、字符串、数字、列表等。列表在 Tcl脚本中使用的频率非常高,基本上每个脚本都会涉及到列表的一些操作,Tcl 中提供了很多对列表操作的命令。本节介绍基本的列表list 命令,包含数据元素在list中的插入、删除、取出、计算,替换等命令。
list相关命令:l+[Tap]+空格
1.1、创建列表
创建list三种方法:
示例:
set list_a "a1 a2 a3"
set list_a {a1 a2 a3}
set list_a [list a1 a2 a3]
1.2、检索元素
index 命令
格式1:
list ?index...?
检索list中的第几个元素。从0开始算。
示例:
lindex $list_a 1
a2
结合foreach命令
格式2:结合foreach访问所有元素。
示例:
% set list_a "a1 a2 a3 a4"
a1 a2 a3 a4
% foreach index $list_a {
puts "$index"
}
a1
a2
a3
a4
lrange 命令
格式3:
lrange list first last
与index相似,返回从first到last的元素。
示例:
% lrange $list_a 0 1
a1 a2
llength命令
格式4:
llength list
返回元素个数。
示例:
% llength $list_a
3
1.3、检索插入删除
lappend 命令
格式1:
lappend listVar ? arg1 arg2 ...argn?
在列表变量listVar后面追加arg1 arg2 …argn?,listVar是一个列表变量,而非列表。
示例:
% set list_a "a1 a2 a3 a4"
a1 a2 a3 a4
% lappend list_a b1 b2
a1 a2 a3 a4 b1 b2
concat 命令
格式2:
concat ?list list...?
把不同list合并为新的list 。
示例:
% concat $list_a {a4 a5}
a1 a2 a3 a4 a5
linsert 命令
格式3:
linsert list index value ?value..?.
在list指定的位置插入新元素。在1之前插入。
示例:
linsert $list_a 1 aa
a1 aa a2 a3
lreplace 命令
格式4:
lreplace list first last ?value value...?
把list 中从first到last的元素改为0个或者多个元素。改变和删除。
示例:
lreplace $list_a 0 1 aa bb
aa bb a3
lreplace $list_a 0 1
a3
lset 命令
格式5:
lset varName ?index...? newvalue
将变量varName 中的index位置的元素改为newvalue 。
示例:
lset list_a 1 xx
a1 xx a3
lsearch 命令
格式6:
lsearch ?option ...? list pattern
在list中搜索与pattern 匹配的一个或多个元素。Option控制模式匹配方式**(-exact,-glob,-regexp),是返回元素值(-inline)还是索引,是搜索所用的匹配(-all)还只是搜索最先出现的匹配等
默认使用-glob匹配,返回第一处匹配的索引,没有匹配元素时返回-1.。
命令option 比较多,建议使用时用man lsearch查看**。
示例:
a1 a2 a3 a4 b1 b2
% set x [lsearch $list_a *3]
2
%
lreplace 命令
格式7:
lreplace list first last ?value value...?
把list 中从first到last的元素改为0个或者多个元素。改变和删除。
示例:
lreplace $list_a 0 1 aa bb
aa bb a3
lreplace $list_a 0 1
a3
lrepat 命令
格式8:
lrepat number value ? value...?
把value重复number次,得到新list。
示例:
lrepeat 2 $list_a
{a1 a2 a3 a4} {a1 a2 a3 a4}
lassign 命令
格式9:
lassign list VarName ?VarName... ?
把list元素依次赋给名为VarName 的变量。把list_a的值赋给 x y z q。
示例:
lassign $list_a x y z q
$x
invalid command name "a1"
二、数组
数组元素以字符串为索引,数组内部使用散列表来存储,其存储速度比列表快。
数组由数组名+索引值组成,索引值对应的数。
array -help查询常用到的命令。
2.1、创建数组
用set命令创建:
格式:
set arrName(index) value
示例:
set color(red) 1
1
set color(gre) 2
2
set color(blu) 3
3
array names color
gre blu red
array get color
gre 2 blu 3 red 1
array size color
3
创建数组color 第1个元素索引值red,数值为1;
创建数组color 第2个元素索引值gre,数值为2;
创建数组color 第3个元素索引值blu,数值为3;
统计数组color 的索引值;
统计数组color 的索引值和其对应的数值;
统计数组color 的大小。
用array命令创建:
格式:
array set arrName{index1 value1 index2 value2 …}
示例:
array set array1 [list {1} {a 92}\
{2} {b 78}\
{3} {c 67}\
{4} {d 45}]
parray array1
array1(1) = a 92
array1(2) = b 78
array1(3) = c 67
array1(4) = d 45
2.2、操作数组
2.2.1、输出数组内容
语法:
parray arr
打印arr的所有变量名和元素值。
2.2.2、数组大小
语法:
array size arrayName
返回arrayName中元素个数。
2.2.3、判断数组是否存在
语法:
array exist arrayName
判断arrayName是否为一个数组,是返回1,否则0。
2.2.4、获取数组元素索引
语法:
array name arrayName
返回arrayName中元素索引名与模式pattern匹配的元素索引名列表。
2.2.5、数组与列表转化
语法:
array get arrayName
array set arrayName dataList
array get是提取数组索引、元素值并组织成一个列表;
array set是将列表转化为一个数组。
示例1:
array set arrayl [list {123} {a A} \
{234} {b B} \
{345} {c C} \
{456} {d D} ]
puts "Arrayl has [array size arrayl] entries\n"
Arrayl has 4 entries
puts "Array1 has the following entries: \n [array names arrayl]"
Array1 has the following entries:
345 234 123 456
puts "ID Number 123 belongs to $arrayl(123)\n"
ID Number 123 belongs to a A
示例2:
array set a [list "123,BUPT" "BUPT" "234,NJU" "NJU" "456,NJUA" "NJUA"]
array names a "*2*,*"
123,BUPT 234,NJU
2.2.6、删除数组元素
语法:
array unset arr ?pattern?
删除符合pattern的数组元素,模式string match,如果不指定模式则删除整个数组。
示例:
array unset a "*2*,*"
a(456,NJUA) = NJUA
三、控制结构
在TCL中包含了与c类似的控制命令,包括if-else、foreach、for、while、switch。
3.1 if命令
语法:
if test1 body1? elseif test2 body2 elseif…?else bodyn?
TLC把test1作为一个表达式求值,值为真则把body1作为脚本执行,否则把test2作为表达式求职,为真把body2作为脚本执行····。
1、 { 一定要写在上一行,否则TCL解释器就会认为 if 在换行符出已经结束,下一行会被当成新的命令,从而解释器报错。但是在一个{ }内部换行则不会报错。
2、可选项 elseif 或者 else 必须要和 if 执行脚本后的 } 在一行。
3、 if 和 { 之间要有一个空格,否则tcl解释器把他们当做一个整体,报错。
示例:
set x 9
9
if {$x > 0} {
puts "x is a + num"
} else {
puts "x is a - num"
}
x is a + num
3.2 switch命令
语法:
switch ?option? String pattern body ?pattern boody ...?
-exact :精确模式匹配;
-glob :缺省匹配;
-regexp :正规表达式匹配;
-- :代表switch指令的flag设定已结束。
switch指令将一个给定的模式和其他模式比较,执行符合匹配模式的脚本,只有一个被执行,其余被忽略,没有匹配则执行default项对应脚本。在switch中通常用{ }抑制替换。
示例:
set sum 0
0
set x 0
0
while {$x < 5} {
set sum [expr $sum + $x]
incr x
}
echo "sum = $sum"
"sum = 10"
3.3 for命令
for循环与c语言类似,需要四个参数,第一个参数设定循环起始条件,第二个参数进行条件测试,第三个参数每一次循环结束后都执行,第四个参数是脚本。
示例:
set y 0
0
% for {set x 1} {$x <= 10} {incr x 1} {
set y [expr $y + $x] }
% puts "y = $y"
y = 55
3.4 foreach命令
foreach varname list body
varname是一个变量,list是一个列表,body是循环体,每次都取列表中的一个元素赋给变量,并执行一次脚本。
示例:
0+1+2+3+4
示例1:
set list "0 1 2 3 4"
0 1 2 3 4
foreach num $list {
set sum [expr $sum + $num]
}
echo "sum = $sum"
"sum = 10"
示例2:
set x {}
foreach {i j} {a b c d e f} {
lappend x $j $i}
puts $x
b a d c f e
示例3:
set list_a "0 1 2 3 4"
0 1 2 3 4
% set list_b "0 1 2 3 4"
0 1 2 3 4
% set sum 0
0
% foreach num1 $list_a num2 $list_b {
set sum [expr $sum + $num1 + $num2]
}
% echo "sum = $sum"
"sum = 20"
3.5 while命令
While test body
参数test是一个表达式,body是一个脚本。如果表达式结束结果非0,则运行脚本,直到表达式为0停止循环。此时while命令中断返回一个空字符串。
示例
0+1+2+3+4
示例:
set sum 0
0
set x 0
0
while {$x < 5} {
set sum [expr $sum + $x]
incr x
}
echo "sum = $sum"
"sum = 10"
四、过程
Tcl中的过程与C语言中子程序一样,是模块化的主要手段。当调一个过程时,它就会变成一个Tcl命令。proc指令第一个参数是过程的名称,第二个参数是过程的参数,第三个参数是过程中的脚本。除非用return 命令表明过程有返回值,否则Tcl会将程序最后一行命令的执行结果作为过程返回值。
4.1:参数待定
proc procName argList body
示例1:
set a 1;
1
proc add {num1 num2} {
global a
set sum [expr $num1 + $num2 + $a]
return $sum
}
add 2 3
6
示例2:
proc alu {type num1 num2} {
if {[string equal $type add]} {
set result [expr $num1 + $num2]
} elseif {[string equal $type mul]} {
set result [expr $num1 * $num2]
}
return $result
}
alu add 2 3
5
alu mul 2 3
6
4.2:默认参数
函数内部参数有默认值,则默认参数值必须写在最右边。
示例:
proc alu {num1 num2 {type add}} {
if {[string equal $type add]} {
set result [expr $num1 + $num2]
} elseif {[string equal $type mul]} {
set result [expr $num1 * $num2]
}
return $result
}
alu 1 2
3
4.3:多个参数
#参数后面加上args,可实现任意数量参数传递
示例:
proc alu {type num1 num2 args} {
puts "argument number is [llength $args]"
if {[string equal $type add]} {
set result [expr $num1 + $num2]
foreach i $args {
incr result $i
}
} elseif {[string equal $type mul]} {
set result [expr $num1 * $num2]
foreach i $args {
set result [expr $result * $i]
}
}
return $result
}
alu add 1 2 3 4 5
argument number is 3
15
% alu mul 1 2 3 4 5
argument number is 3
120
当使用args参数时,通常在过程内部,可以将输入参数“名+值”的列表转化为数组,每个参数名就成了数组元素,对应参数值成了对应数组元素的值。
示例:
proc test2 {args} {
array set inpara $args;#定义一个数组,数组中的元素索引和值通过 args输入
parray inpara
return [expr $inpara(1) * $inpara(2)];#计算索引为 0和索引为 1的数组元素
}
% test 1 3 2 5 3 6
inpara(1) = 3
inpara(2) = 5
inpara(3) = 6
15