TCL脚本语言-8-控制结构

  • 格式:pdf
  • 大小:487.91 KB
  • 文档页数:20

下载文档原格式

  / 20
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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" }

#放到这里,是错误的注释