控制流

介绍控制流命令,对之前系列TCL脚本语言的学习(一)进行补充

if

语法: if test1 body1 ?elseif test2 body2 elseif…. ? ?else bodyn?
TCL 先把 test1 当作一个表达式求值,如果值非 0,则把 body1 当作一个脚本执行并返回所得值,否则把 test2 当作一个表达式求值,如果值非 0,则把 body2 当作一个脚本执行并返回所得值……。例:

if { $x<0 } {
puts "x is smaller than zero"
} elseif {$x==1} {
puts "x is equal 1"
} elseif {$x==2} {
puts "x is equal 2"
} else {
puts "x is other"
}

这里需要注意的是,
if 和{之间应该有一个空格,否则TCL解释器会把’if{‘作为一个整体当作一个命令名,从而导致错误。
‘{‘一定要写在上一行,因为如果不这样,TCL 解释器会认为if命令在换行符处已结
束,下一行会被当成新的命令,从而导致错误的结果需要将}{ 分开写,
否则会报错extra characters after close-brace

循环命令

while

语法为: while test body
参数 test 是一个表达式,body 是一个脚本,如果表达式test 的值非 0,就运行脚本,直到表达式为0 才停止循环,此时 while 命令中断并返回一个空字符串。
例如:

set a {a b c d e}
set b " "
set i [expr [llength $a]-1]
while {$i>=0} {
lappend b [lindex $a $i]
incr i -1
}
puts "b=$b"

对代码进行分析
set 变量a为一个list,b为一个空list
然后计算列表里有几个元素,将其减一后的值赋值给i,这里减一的目的是从零开始计数会多一个
开始进行循环,首先i的值是4大于0,表达式为真,开始执行脚本。
脚本为将数组a的第i个位置的元素添加到b list 里,然后给i减一同时进行下一次判断即可。
最后输出b的值

b=e d c b a

for

语法为: for init test reinit body
参数init是一个初始化脚本,第二个参数test是一个表达式,用来决定循环什么时候中断,第三个参数reinit是一个重新初始化的脚本,第四个参数body也是脚本,代表循环体。

for {set p 0} {$p<=10} {incr p} {
puts "$p squared is : [expr $p*$p]"
}

执行结果为

0 squared is : 0
1 squared is : 1
2 squared is : 4
3 squared is : 9
4 squared is : 16
5 squared is : 25
6 squared is : 36
7 squared is : 49
8 squared is : 64
9 squared is : 81
10 squared is : 100

foreach

foreach varName list body 第一个参数 varName 是一个变量,第二个参数 list 是一个表(有序集合),第三个参数 body 是循环体。每次取得链表的一个元素,都会执行循环体一次。这里对于复杂的操作不进行解释,参考文章一

set a [list A B C D E F G]
set b ""
foreach i $a {
set b [linsert $b 0 $i]
}
puts $b

运行结果为

G F E D C B A

赋值给变量

% foreach {x y} {a b c d } {
puts "$x $y"
}
a b
c d

又例如:

% foreach i {a b} {j k} {v W x y z} {
puts "i=$i,j=$j,k=$k"
}
i=a,j=v,k=W
i=b,j=x,k=y
i=,j=z,k=

break和continue命令

在循环体中,可以用break和continue命令中断循环。其中break命令结束整个循环过程,并从循环中跳出,continue只是结束本次循环
这里有一个特别好的例子
说明:这里首先进行给一个list,然后使用foreach循环进行写入数据当遇见break时候直接退出了循环,而continue仅仅只是跳出此次循环继续向b里写入数

% set b {}
% set a {1 2 3 4 5}
1 2 3 4 5
% foreach i $a {
if {$i == 4} break
set b [linsert $b 0 $i]
}
% puts $b
3 2 1
% set b {}
% set a {1 2 3 4 5}
1 2 3 4 5
% foreach i $a {
if {$i == 4} continue
set b [linsert $b 0 $i]
}
% puts $b
5 3 2 1

switch

和 C 语言中 switch 语句一样,TCL 中的 switch 命令也可以由 if 命令实现。只是书写起来较为烦琐。 switch 命令的语法为: switch ? options? string { pattern body ? pattern body …?}
注意这里进行的是字符匹配

set x a;
set t1 0;set t2 0;set t3 0;
switch $x {
a -
b {incr t1}
c {incr t2}
default {incr t3}
}
puts "t1=$t1,t2=$t2,t3=$t3"

x=a时执行的是t1加2
其中 a 的后面跟一个’-’表示使用和下一个模式相同的脚本。default 表示匹配任意值。一旦switch 命令 找到一个模式匹配,就执行相应的脚本,并返回脚本的值,作为 switch 命令的返回值。

set grade B;
switch $grade {
A {
puts "Well done!"
}
B {
puts "Excellent!"
}

C {
puts "You passed!"
}
F {
puts "Better try again"
}
default {
puts "Invalid grade"
}
}
puts "Your grade is $grade"

source

source 命令读一个文件并把这个文件的内容作为一个脚本进行求值
以上边的switch第一段代码为例
使用VIM新建一个文件,写入文件后保存退出

vim switch1.tcl

键入wish然后输入source switch1.tcl

过程(procedure)

TCL 支持过程的定义和调用,在 TCL 中,过程可以看作是用 TCL 脚本实现的命令,效果与 TCL的固有命令相似。我们可以在任何时候使用 proc 命令定义自己的过程,TCL 中的过程类似于 C中的函数。
TCL 中过程是由 proc 命令产生的:
例如:

% proc add {x y } {expr $x+$y} 

proc 命令的第一个参数是你要定义的过程的名字,第二个参数是过程的参数列表,参数之间用空格隔开,第三个参数是一个 TCL 脚本,代表过程体。 proc 生成一个新的命令,可以象固有命令一样调用:

% add 1 2
3

此篇暂时这里结束,后又需要会继续记录