TCL脚本语言简介
• TCL( Tool Command Language) 是一种解释执行的脚本语言( Scripting Language) ,它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。
• 实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是一个库包,可以被嵌入应用程序,Tcl的库包含了一个分析器、用于执行内建命令的例程和可以使你扩充(定义新的过程)的库函数。每个应用程序都可以根据自己的需要对TCL语言进行扩展。
• 扩展后的TCL语言将可以继承TCL核心部分的所有功能,包括核心命令、控制结构、数据类型、对过程的支持等;TCL良好的可扩展性使得它能很好地适应产品测试的需要,目前已成为自动测
试中事实上的标准。
Tcl基础入门
脚本学习核心
• TCL脚本执行依赖于解释器(逐行执行)。
• TCL有效命令行以命令+字符串(结合空格间隔符)形成
• 明白置换($、[]、\)和引用(''",{})的差别和联系。
• 理解命令eval、expr、source、exec的差别。
• 掌握{*}配合glob等返回list后的操作
基础语法
• 一个TCL脚本可以包含一个或多个命令。命令之间必须用换行符或分号隔开,下面的两个脚本都是合法的:
set a 1
set b 2
或set a 1; set b 2
• TCL每一命令包含一个或几个单词,第一个单词代表命令名,另外的单词则是这个命令的参数,单词之间必须用空格或TAB键隔开。
•注释:使用#注释,set foo 0; #注释内容,注释符号前应该有分号,因为tcl解析器总是认为一条命令应该以换行或者分号结束,其他的在同一行中都认为是参数。
置换(substitution )
• TCL解释器在分析命令时,把所有的命令参数都当作字符串看待,数据类型:tcl不支持其他语言中的形如int, double ,char等等类型,唯一支持的就是string类型。例如:
set x 10 ; #定义变量x,并把x的值赋为10
10
set y x+100 ;#y的值是x+100,而不是我们期望的110
x+100
上例的第二个命令中,x被看作字符串x+100的一部分,如果我们想使用x的值'10',就必须告诉TCL解释器:我们在这里期望的是变量x的值,而非字符'X',怎么告诉TCL解释器呢,这就要用到TCL语言中提供的置换功能。
• TCL提供三种形式的置换:变量置换、命令置换和反斜杠置换.
变量置换
•变量置换由一个$符号标记,变量置换会导致变量的值插入一个单词中。例如:
set y $x+100; #y的值是10+100,这里x被置换成它的值10
10 + 100
•这时,y的值还不是我们想要的值110,而是10+100,因为TCL解释器把10+100看成是一个字符串而不是表达式,y要想得到值110,还必须用命令置换,使得TCL会把10+100看成一个表达式并求值。
命令置换
•命令置换是由[ ]括起来的TCL命令及其参数,命令置换会导致某一个命令的所有或部分单词被另一个命令的结果所代替。例如:
set y [expr $x+100];
110
• y的值是110 , 这里当TCL解释器遇到字符'['时,它就会把随后的expr作为一个命令名,从而激活与expr对应的C/C++过 程,并把'expr'和变量置换后得到的'10+110' 传递给该命令过程进行处理。
• 如果在上例中我们去掉 [ ],那么TCL会报错 。因为在正常情况下 ,TCL解释器只把命令行中的第一个单词作为看作命令,其他的单词都作为普通字符串处理,看作是命令的参数。
反斜杠置换
• TCL语言中的反斜杠\置换似于C语言中反斜杠的用法,主要用于在单词符号中插入诸如换行符、空格、[、$等被TCL解释器当作特殊符号对待的字符。例如:
set msg multiplex\ space; #msg的值为multiple space。
multiple space
•如果没有'\'的话,TCL会报错,因为解释器会把这里最后两个单词之间的空格认为是分隔符,于是发现set命令有多于两个参数,从而报错。加入了'\‘后,空格不被当作分隔符,'multiple space‘被认为是一个单词(word)。
• TCL支持以下的反斜杠置奂:
例如:
set a \x48 ; #对应 \xhh
H #十六进制的48是72,对应字符H
双引号和花括号
• 除了使用反斜杠外,TCL提供另外两种方法来使得解释器把分隔符和置换符等特殊字符当作普通字符,而不作特殊处理,这就要使用双引号" "和花括号({})。
• TCL解释器对双引号中的各种分隔符将不作处理,但是对换行符及$和[ ]两种置换符会照常处理。
set y "$x ddd";
100 ddd
• TCL中的注释符'#','#'和直到所在行结尾的所有字符都被TCL看作注释,TC解释器对注释将不作任何处理。
变量
变量:简单变量
一个TCL简单变量包含两个部分 :名字和值。名字和值都可以是任意字符串。
TCL解释器在分析一个变量置换时,只把从$符号往后直到第一个不是字母、数字或下划践的字符之间的单词符号作为要被置换的变量的名字。变量:在tcl变量不需要声明就可以直接赋值,
set a 2 ; set a.1 4; set b $a.1;
2 4 2.1
• 在最后—命令行,我们希望把变量a.1的值付给b,但是TCL解释器在分析时只把$符号之后直到第一个不是字母、数字或下划线的字符(这里是之间的单词符号(这里是'a')当作要被置换的变量的名字,所以TCL解释器把a置换成2,然后把字符串付给变量b。这显然与我们的初衷不同。
•如果变量名中有不是字母、数字或下划线的字符,又要用置换,可以用花括号把变量名括起来。
set b ${a.1};
4
•TCL中的set命令能生成一个变量、也能读取或改变一个变量的值
set a {kdfj kjdf} ; # 变量a的值是kdfj kjdf
set a; #读取变量a的值
变量:数组
•数组是一些元素的集合。TCL数组和普通计算机语言中的数组有很大的区别。在TCL中,不能单独声明一个数组,数组只能和数组元素一起声明。数组中,数组元素的名字包含两部分:数组名和数组中元素的名字,TCL中数组元素的名字(下标)可以为任何字符串。
set day(monday) 1;
set day(tuesday) 2;
• 第一个命令生成一个名为 day 的数组 , 同时在数组中生成 一个名为monday的数组元素,并把值置为1,第二个命令生成一个名为tuesday的数组元素,并把值置为2。
相关命令
• unset这个命令从解释器中删除变量,它后面可以有任意多个参数,每个参数是一个变量名,可以是简单变量,也可以数组或数组元素。
unset a b day(monday)
• append命令把文本加到一个变量的后面
set txt hello; #hello
append txt"! How are you"; #hello! How are you
• incr命令把一个变量值加上一个整数。incr要求变量原来的值和新加的值都必须是整数。
set b 2; incr b 3; #结果为5
表达式
• TCL支持常用的数学函数,表达式中数学函数的写法类似于C\C++语言的写法,数学函数的参数可以是任意表达式,多个参数之间用逗号隔开。
set x 2; #变量x的值是2
expr 2* sin($x<3); #表达式的值为1.68294196962
•其中expr是TCL的一个命令,语法为:expr arg ?arg ...?
两个?之间的参数表示可省,后面介绍命令时对于可省参数都使用这种表示形式。
•需要注意的一点是,数学函数并不是命令,只在表达式中出现才有意义,即出现在expr之后才有意义。
List
•list这个概念在TCL中是用来表示集合的。TCL中list是由一堆元素组成的有序集合,list可以嵌套定义,list每个元素可以是任意字符串,也可以是list。
{} #空 list
{abed} {a {b c} d} #list可以嵌套
•语法:list value value...
•这个命令生成list,就是所有的value。
list 1 2 {3 4} ; # list的元素是1 2 {3 4}
•语法:concat list list... #整合两个list
concat {1 2 3} {4 5 6} #整合后的list为{1 2 3 4 5 6)
•语法:lindex list index #返回list的第index个元素
lindex {1 2 {3 4}} 2 #返回list的第2个元素3 4
•语法:llength list #返回list的元素个数
llength {1 2 {3 4}} #3
•语法:linsert list index value value… #list插入元素
linsert {1 2 5 6} 1 7 8 #1 7 8 2 5 6
• 语法:lappend varname value value...
把每个vaIue的值作为一个元素附加到变量vamame后面
lappend a 1 2 3 #1 2 3
控制流:if命令
•语法:if test1 body1 else bodyn
TCL先把test1当作一个表达式求值,如果值非0。则把body1当作一个脚本执行并返回所得值,否则把test2当作一个表达式求值,如果值非0,则把body2当作一个脚本执行并返回所得值。
if { $x>0 }{ #注意'{'一定要写在上一行,因为不这样,TCL解释器会认为if命令在换行符已经结束了;
..… #同时if和'{'之间应该有空格否则TCL解释器会把if'{'作为一个整体命令导致出错
}elseif {$x==1} {
… } elseif { $ x = = 2 } {
....}else{
….}
循环命令:while
•语法:while test body
参数test是一个表达式,body是脚本,如果表达式的值非0,就运行脚本,直到表达式为0才停止循环,此while命令中断并返回一个空字符串。此处是一个脚本:
set b " "
set i [expr [llength $a] -1]
while { $i>=0}{
lappend b [lindex $a $i]
incr i-1
)
〃变量a是一个链表,脚本把a的值复制到b
循环变量:for
•语法:for init test reinit body
参数init是一个初始化脚本,第二个参数test是一个表达式 ,用来决定循环什么时候中断,第三个参数reinit是重新初始化的脚本,第四个参数body也是脚本,代表循环体;
假设变量a是一个链表,下面的脚本把a的值复制到b:
set b " "
for {set i [expr [llength $a] -1]} {$i>=0} {incr i -1) {
lappend b [lindex $a $i] }
#作用和上面的例子是相同的。
#例如:
for {set i 0} {$i< 10} {incr i} {puts $i;} #将打印出0到9
foreach命令
• 语法:foreach varName list body
第一个参数varName是一个变量,第二个参数list是一个表(有序集合),第三个参数body是循环体。每次取得链表的元素都会执行循环体一次。
set b " "
foreach i $a{
set b [linsert$b 0 $i]
}
变量a是一个链表,脚本把a的值复制到b。
switch命令
• 语法:switch options string ( pattern body pattern
body ... }
第一个是可选参数options,表示进行匹配的方式。TCL持三种匹配方式:-exact方式,-glob方式,-regexp方式,缺省情况表示-glob方式。-exact方式表示的是精确匹配,-glob方式的匹配方式和string match命令的匹配方式相同,-regexp方式是正规表达式的匹配方式。第二个参数string是要被用来作测试的值,第三个参数是括起来的一个或多个元素对。
switch $x { #一旦switch命令找到一个模式匹配
b {incr t1} #就执行相应的脚本,并返回脚本的值,作为switch命令的返回值
c {incr t2}
}
switch $x {
数值1 { 操作1 ;}
数值2 { 操作2 ;}
}
命令
•在循环体中,可以用break和continue命令中断循环。其中break命令结束整个循环过程并从循环中跳出,continue只是结束本次循环。
• source命令读一文件并把这个文件的内容作为一个脚本进行求值
source e:/tcl&c/hello.tcl
• eval命令是一个用来构造和执行TCL脚本的命令,其语法为:
eval arg arg ... #它可以接收一个或多个参数,然后把所有的参数以空格隔开组合到一起 成为一个脚本,然后对这个脚本进行求值。
eval set a 2 ;set b 4