TCL脚本语言-8-控制结构
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
控制结构
TCL中使用命令来实现程序控制结构,我们还可以自己编写扩展命令来扩充控制结构。常见的控制结构包括如下几种:
循环控制、条件判断、异常处理和执行脚本。这些结构控制命令都比较简单,和C/C++中的程序控制比较类似。但是在介绍控制结构之前,先有必要介绍一下Tcl中的布尔类型。
Boolean类型
再次强调,TCL中一切都是字符串,没有类型。这里所说的Boolean类型,指的是在条件判断的时候,什么东西被当作True,什么被当作False。请记住如下规则:
1.字符串:Yes,Y,True,T,On。不管大小写,当作条件来判断时,会被认为是True;
2.字符串:No,N,False,F,Off。不管大小写,当作条件来判断时,会被认为是
False;
3.数字0(整数或者浮点)会被当作False,任何非0的整数或者浮点数都会被当作
True;
例如:
% while 0.00e23 "puts ccc;break;" ;#False
% while 0. "puts ccc;break;" ;#False
% while 0.1 "puts ccc;break;" ;#True
ccc
% while T "puts ccc;break;" ;#True
ccc
% while 1023 "puts ccc;break;" ;#True
ccc
% while T "puts ccc;break;" ;#True
ccc
条件判断
TCL中的条件判断主要是两个命令:if和switch。
if…else
if命令的格式如下:
if expr1 ?then? body1elseif expr2 ?then? body2elseif ... ?else? ?bodyN?
可以看见,if命令的参数then是可以省略的。这给喜欢Pascal风格和C风格的不同的编程人员,都带来了怀旧的机会。Pascal中then是必须的。C中是没有then的。
if命令中的条件表达式expr可以写成多行,只要是一个字符串都可以。如果写成多行,那么最好加上then,这样看起来就比较方便。
这个命令的具体执行我就不详细解释了。要注意的是最后的else,如果没有else,那么就不能有bodyN,如果有了else,就必须有bodyN。请看例子:
if {$vbl == 1} {
puts "vbl is one"
} elseif {$vbl == 2} {
puts "vbl is two"
} else {
puts "vbl is not one or two"
}
switch
相比if…else,switch命令则要复杂很多。它有两种语法形式:
1.switch ?options? string pattern body ?pattern body ...?
2.switch ?options? string {pattern body ?pattern body ...?}
两种形式功能上完全等价,我们一般建议采用第二种,它和C语言的语法比较接近:所有的候选值和对应的代码全部都放在一个花括号中。但是如果需要对pattern和body等进行替换,那么第一个形式就比较方便。
switch的选项参数可以为:
1.-exact:这是默认情况,表示参数string和模式pattern的精确匹配;
2.-glob:表示采用glob模式进行匹配。匹配方法参考string match命令;
3.-regexp:表示采用正则表达式进行匹配,string是字符串,而pattern是正则表达式;
4.--:表示选项参数到此为止,后面的是参数string。这是为了防止参数string的第一
个字符就是“-”而引起非法选项的错误。
该命令的执行过程:根据选项指定的匹配模式,逐个将string和pattern进行匹配,如果匹配成功,那么就执行pattern后面对应的代码,并且返回该代码的结果。如果最后的一个模式是default,安么它匹配任意字符串。如果string没有一个匹配成功并且没有default,那
么switch直接返回空。
如果某一个pattern对应的body为“-”,那么表示这个pattern和下一个pattern共享一个body。这和C语言中的case 1:case2:{…}比较类似。
switch中的-regexp
请看下面的几个例子:
set r "abbbcc"
switch -regexp $r {
ab{2}c { puts "1" }
ab{3}c { puts "2" }
ab{3}c{2} { puts "3" }
}
上面采用正则表达式进行匹配,显然,第三个表达式才是和$r完全匹配的。但是上面的代码执行输出是“2”。这给我们一个重要的启示:
switch中的-regexp匹配选项,实质上就是把pattern拿出来在string中进行正则表达式查找,也就是执行regexp命令,如果regexp返回1(也就是在string中找到了pattern),那么就算匹配成功,就开始执行后面的body。而根本不管pattern是不是恰好匹配了整个string!
上面这一点务必牢记。
对-glob选项,则没有这样的问题。选项pattern和string只有完全匹配的时候才算匹配成功。也就是说执行命令string match $pattern $string返回1,才算匹配成功。
注释的位置
如果使用switch的第二种语法形式,那么就要注意switch中注释的正确位置。注释只有放在各个body中才是正确的注释,如果放在其它地方,会出现语法错误。例如:
set r "abbbcc"
switch -glob $r {
a {
#匹配失败,不可能执行到这里
puts "1"
#正确的注释
}
a*cc { puts "2" }
#放到这里,是错误的注释