您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 信息化管理 > TCL脚本语言-3-置换:TCL的灵魂
TCL、Python和软件测试自动化13作者:雷雨后Email:leiyuhou010@gmail.com基本词法和概念在进一步深入了解TCL的语法之前,弄清楚TCL脚本的几个基本概念以及TCL解释器解释执行一个脚本的基本流程,是很有必要的。一切都是命令和及其参数TCL脚本语法的本质其实非常简单:1.一个脚本是由一个或多个命令以及其参数顺序排列而成;命令之间用换行字符或者分号分隔;TCL中的一切都是命令及其参数。2.一个命令语句包括一个命令字以及零个或多个该命令的参数;命令和参数以及参数之间用空格或者Tab分隔;3.如果任何地方出现可以进行置换的操作,那么就会按照规则进行置换;例如下面的一段代码实际上是由三个命令组成的:classCPerson{;#第一条命令class及其两个参数protectedvariablem_name;#成员变量,保护类型,可以被继承protectedvariablem_sexconstructor{namesex}{;#构造函数setm_name$namesetm_sex$sex}publicmethodPrintInfo{}{;#public方法,输出对象信息,可以被继承putsCPerson[GetInfo];#调用了成员函数GetInfo}publicmethodGetInfo{}{returnname=$m_name;sex=$m_sex;#返回对象信息}};#第一条命令结束。CPersona“LeiYuhou”Male;#第二条命令aPrintInfo;#第三条命令TCL、Python和软件测试自动化14作者:雷雨后Email:leiyuhou010@gmail.com上面代码很长,但是实际上只有三个命令:第一个是class命令,带有两个参数,第一个是类名,第二个是类的定义体;第二个命令是CPerson命令,实际上刚才的class命令在执行之后就定义了一个新的TCL命令,命令名就是我们声明的类名;第三个命令的命令字是a,这是我们刚才创建的对象,实际上CPerson命令在执行的时候又创建了一个TCL命令,其名字就是我们给出的对象名。命令之间只有两种分隔符号:分号或者换行符号。所以如果我们要把两个命令写在一行,那么必须使用分号分隔它们。例如上面的后两个命令:CPersona“LeiYuhou”Male;aPrintInfo要注意的是,并不是所有的分号和换行符号都是命令分隔符!!例如下面的代码:if{$a100}{puts“a=$a”}三行代码,三个换行符只有最后一个是if命令的分隔符;而前两个相对于if命令而言,只是其第二个参数中的字符而已。初学者往往会把上面的代码写成下面两种形式:if{$a100}{;#条件判断的}后面没有空格,直接跟着{puts“a=$a”}if{$a100};#条件判断的后面直接回车,把执行体的{放到下一行{puts“a=$a”}两种写法都是错误的。错误代码分别如下:extracharactersafterclose-bracewhileexecutingif{$a100}{putsa=$a}wrong#args:noscriptfollowing$a100argumentwhileexecutingif{$a100}第一种情况,{$a100}和后面的{之间没有空格,那么就会报错:因为不符合单词的语法。第二种情况,{直接拿到了if命令的第二行,那么TCL认为这里的if命令在本行就结束,那么if命令就只有一个参数,显然也会报错。TCL、Python和软件测试自动化15作者:雷雨后Email:leiyuhou010@gmail.com什么时候回车字符作为命令结束符,什么时候又不是?为什么会出现第一种错误?回答这些问题之前,我们必须弄清楚另外一个重要概念:单词!单词、引号、括号一个脚本是由多个命令顺序排列而成;而一个命令则是由多个单词组成。单词是由空格来进行分隔的一个字符串,例如下面的命令中:seta100就包含了三个单词:set、a和100但是也有一些特殊情况:双引号如果一个单词以一个双引号字符开始,那么这个单词会以下一个双引号作为结束。如果在这两个双引号之间出现了分号“;”、反方括号“]”、以及空格或者换行字符,那么这些字符都作为单词中的字面字符出现,它们不具备任何特殊含义。开始和结束的双引号不作为这个单词内的字符。例如:seta100;#命令1”set”“a”“100”;#命令2setb“FirstSecond”;#命令3setbFirstSecond;#命令4,错误setc“ThefirstlineThesecondline”上面代码中,前面两个命令是完全等价的,虽然命令2中三个单词都用双引号括起来,但是三个单词和命令1中的三个单词完全一样。执行后变量a的值都为100;命令3中第三个单词用引号括起来,其中包含了空格,如果没有引号,象命令4中所示,那么就会出现错误。因为set命令不能够接受三个参数。最后一个命令中也包含三个单词,最后一个单词是用引号括起来的跨行字符串,里面包含了换行符号。用双引号括起来的单词中,所有的置换类型都可以发生。具体我们后面在置换一节中详细解释。花括号如果一个单词以字符“{”开始,那么它必须以相对应的反括号字符“}”作为结束。单TCL、Python和软件测试自动化16作者:雷雨后Email:leiyuhou010@gmail.com词内部的花括号可以嵌套,但是它们必须配对出现;如果某一个花括号前面是反斜线,那么TCL解释器在寻找配对括号的时候该括号不计算在内。该单词是所有出现在花括号在内的原始字符,但是不包含开始和结束的花括号。例如下面的代码:seta{{青山依旧在,}{几度夕阳红。}}setb{\{SatHello\}}puts$aputs$bsetb{\{SatHello}}代码执行结果如下:{青山依旧在,}{几度夕阳红。}\{SatHello\}wrong#args:shouldbesetvarName?newValue?whileexecutingsetb{\{SatHello}}最后一行代码出错了,因为set第三个单词内,嵌套的花括号不能匹配上。如果一个单词是用花括号括起来的,那么里面所有的置换都不会发生。我们回归头来看看前面CPerson类的定义,类的定义部分就是一个用花括号括起来的,包含多行字符创的单词。通过上面的分析,可以看到,下面的两块代码在“一定程度上”是等价的:if{$a100}{puts“a=$a”}if“$a100”“puts\“a=$a\””为什么说是“一定程度”呢,我们有必要了解TCL解释执行脚本的过程。解释执行过程TCL解释器执行脚本的过程就是:1.根据前面介绍的命令分隔规则和单词划分规则,将脚本文件内容解析成多个命令的TCL、Python和软件测试自动化17作者:雷雨后Email:leiyuhou010@gmail.com序列;2.按照从上到下的顺序,逐个执行命令;3.执行一个命令的时候,a)如果组成命令的单词中存在变量、反斜线换或者命令置换,会根据单词的特点进行置换;b)置换后,把第一个单词作为命令字,到命令库中找到对应的命令执行体;c)如果找到,把后面的单词作为参数传入给命令,执行命令;d)如果没有找到,那么就通过一定的机制继续寻找,如果找不到,就抛出异常;4.所有的命令执行完,那么脚本执行就结束。理解了上面的脚本执行过程,就可以理解上一节所说的“一定程度”是什么意思了:执行器在执行一条命令的之前,首先把命令划分成单词,然后根据单词的写法来进行置换。在上一节左边的代码中,代码被划分成三个单词,但是后面两个单词都是用花括号括着的,所以没有不会发生置换,直接把它们作为参数调用if命令。而右边的代码中,同样是三个单词,只不过后面的两个单词被双引号括着,所以在执行if命令之前,解释器会先对这两个单词进行置换,把里面的$a用a的值替代,然后把替换后的单词作为参数传递给if命令。下面的代码会进入死循环,为什么?大家自行分析。Yes把脚本解析成命令序列全部命令执行?取下一条命令该命令分解成单词必要的置换操作执行该命令执行结束NoTCL、Python和软件测试自动化18作者:雷雨后Email:leiyuhou010@gmail.comseta100seti0setsum0while$i=$a{;#如果换成{$i=$a},就不会死循环了。incrsum$iincri}puts$sum需要指出的是,上面解释执行过程中的第三步是可以嵌套的,也就是说,在执行一个过程的时候,在这个过程内部也可以通过这个过程来执行另外一块脚本代码。就比如上面的while循环,它的第一个参数是条件表达式”$i=$a”,第二个参数是一段代码;在执行while命令的过程中,首先计算条件表达式,根据表达式的值确定是否执行下面的代码,如果条件满足,那么就执行。执行这一段代码的过程和执行while的类似:先划分成命令序列,再顺序执行每一条命令。这一段代码如何执行,是由while命令来控制,而不是TCL解释器所控制的。所以,while不过是一个命令!脚本注释理解了脚本的执行过程,就不难理解TCL中的注释规则:当TCL解释器在解释执行脚本的时候,如果期望下一个单词是一个命令,但是这个单词的第一个字符是“#”,那么从这个“#”开始直到这一行的结束,都被TCL当作注释而忽略过去。下面是几个例子:#这是一行合法的注释seta100;#创建变量a,合法的注释seta100#创建变量a,不合法的注释;for{setsum0;seti0;#初始化}{$i=100}{incri;#递增}{incrsum$i}puts$sum第三行注释不正确,因为这里#以及后面的字符都被解释成了set命令的参数,所以会报错:TCL、Python和软件测试自动化19作者:雷雨后Email:leiyuhou010@gmail.comwrong#args:shouldbesetvarName?newValue?whileexecutingseta100#创建变量a,不合法的注释上面的错误,是我们经常犯的错误。上面例子中,for循环命令中的注释,似乎和前面介绍的TCL注释规则相违背,注释并没有从“#”直到一行结束,而是只到花括号结束。仔细分析,实际上并不违背:例如for的第一个参数,包括里面的注释,是整个作为一个单词被传递给for命令来解释的,for命令执行这个单词的时候,就会正确的解释其中的注释。没有do...while?自己实现TCL中没有do...while循环,但是我们明白了上面的道理之后,完全可以自己实现一个do命令,作为我们自己的一种控制结构。这在其他的Python、Pascal等语言中是很难想象的:python里面没有switch,你试着在python实现一个switch,看能否实现?下面就是一个do命令的简单实现,使用TCL写成:#定义do命令procdo{bodywhile_keycond}{if{$while_key!=while}{errorthesecondparametermustbe\while\.}for{}{1}{}{#使用for循环来执行循环体setr[catch{uplevel$body}msg];#捕获异常信息switch$r{0{#thisisnormal,donothing}1{thisisaerror,sothrowtheexception.return-codeerror-errorinfo$::errorInfo-errorcode$::errorCode}2{#thisisreturn;return-codereturn$msg}3{#thisisbreak;break}TCL、Python和软件测试自动化20作者:雷雨后Email:leiyuhou010@gmail.com4{#thisiscontinue,donothing;}}setr[uplevelexpr$cond]#判断条件,是否应该继续执行。if{!
本文标题:TCL脚本语言-3-置换:TCL的灵魂
链接地址:https://www.777doc.com/doc-5362506 .html