一、脚本、命令和单词符号
一个TCL脚本可以包含一个或多个命令。命令之间必须用换行符或分号隔开。
1、关键字/变量
变量是程序的基础
变量组成:变量名、变量值
变量名要求:任何字符串都可以作为变量名,区分大小写
变量值要求:任何字符串都可以作为变量值
⦁ 变量赋值基本语法:
set varname value;
e.g:
set x 10;
set text “Hello,World”
2、置换
TCL解释器在分析命令时,把所有的命令参数都当作字符串看待,例如
set x 10; #定义变量x,并把x的值赋为10
set y x+100;#定义变量y,y的值是x+100,而不是我们期望的110
上例中的第二个命令中,x被看作字符串x+100的一部分,如果我们想使用x的值'10',就必须告诉TCL解释器:我们在这里期望的是变量x的值,而非字符'x'。怎么告诉TCL解释器呢,这就要用到TCL语言中提供的置换功能。
TCL提供三种形式的置换:变量置换、命令置换和反斜杠置换。每种置换都会导致一个或多个单次本身被其他的值所代替。置换可以发生在包括命令名在内的每一个单词中,而且置换可以嵌套
set x 10
⦁ 变量置换
变量置换由一个$符号标记
set y $x+100; #y的值为10+100,这里x被置换成它的值10;
⦁ 命令置换
命令置换是由[]括起来的TCL命令及其参数
set y [expr $x+100]; #y的值为110;
y的值是110,这里当TCL解释器遇到字符'['时,它就会把随后的expr作为一个命令名,从而激活与expr对应的C/C++过程,并把'expr'和变量置换后得到的'10+100'传递给该命令过程进行处理。
注意:[]中必须是一个合法的TCL脚本,长度不限。[]中脚本的值为最后一个命令的返回值,例如:
set y [expr $x+100;set b 300]; # y的值为300,因为set b 300的返回值为300
⦁ 反斜杠置换
set y \$x+100;#y的值为$x+100;
⦁ 释放变量:
unset x;
3.双引号和花括号
TCL提供另外两种方法来使得解释器把分隔符和置换符等特殊字符当作普通字符,而不作特殊处理,这就要使用双引号和花括号({}).
TCL解释器对双引号中的各种分割符将不作处理,但是对于换行符以及$和[]两种置换符会照常处理。例如
set x 100
set y "$x ddd"; # y的值为100 ddd
而在花括号中,所有特殊字符都将成为普通字符,失去其特殊意义,TCL解释器不会对其作特殊处理。
set y {/n$x [expr 10 +100]}; #y的值为/n$x [expr 10 +100]
4.注释和输出
TCL中的注释符是‘#’,‘#’和直到所在行尾的所有字符都被TCL看作注释,TCL解释器对注释将不作任何处理。
不过,需要注意的是,“#”必须出现在TCL解释器期望命令的第一个字符出现的地方,才被当作注释。例如:
set a 100 # Not a commnet
上述命令不是一个注释,会报错
set a 100; # this is a comment
上述才是一个有效的注释
第一个命令中“#”不被当作注释符,因为它出现在命令行的中间,TCL解释器把它和后面的字符当作命令参数处理,从而导致错误。而第二个命令中“#”就被当作注释,因为前一个命令已经使用了一个分号结束,TCL解释器期望下一个命令接着出现,现在这个位置出现“#”,随后的字符就被当作注释了。
puts :输出文本,多个单词如被空格或TAB分隔需要使用“”或{} 括起来;多个命令写在一行使用 ; 间隔。
puts Hello # 正确
puts Hello,World ; # 正确,多个单词之间不是被空格或者TAB分隔开
puts Hello World; # 这行命令运行出错,被空格分隔
puts "Hello, World - In quotes" ; # 注释
puts {Hello, World - In Braces}
puts "This is line 1"; puts "this is line 2"; # 正确,用分号分隔两个命令
puts "Hello, World; - With a semicolon inside the quotes" ; #正确,分号在双引号内,作为字符串一部分
二、数据类型
tcl的数据类型实际上只有一种:字符串
在tcl中变量没有类型转换或者类型匹配的问题,所有的“数据”都是以字符串的形式存在,那么tcl如何进行数值计算?如何输出一个小数?
数值计算:
tcl支持各种数学函数的数值计算,但是仅能在expr命令中使用
e.g:
set angle 30;
set radian [expr $angle*3.1415926/180.0];
set value [expr sin($radian)];
value值为0.499999992265;
数据类型输出
在输出数据到文件或者屏幕时,format命令可以用于控制显示的格式确保它按要求输出。
e.g:
set vlaue1 [format %.1f $value];
value1的值为0.5;
三、数据结构-List
List是tcl语言里功能给常强大非常灵活的应用最多一种数据结构之一,一个列表可以有任意多个元素,每一个元素都可以是任意的字符串,最简单的列表就是包含由任意个空格、制表符、换行符分隔开的任意多个元素的字符串。
e.g:
john anne mary jim;
创建一个列表
set x [list 1 2 3 4];
按指定分隔符将一个字符串拆分为列表
set string “1,2,3,4”;
set x [split $string “,”];
从列表中取出一个元素
set value1 [lindex $x 0];
set value2 [lindex $x 1];
set value3 [lindex $x 2];
set value4 [lindex $x 3];
四、数据结构-Array
在Tcl中,除了简单变量,还提供了数组,数组是元素的几何,每一个元素都有自己的名称和值。数组由两部分组成,即数组名和数组中的元素名,数组名和元素名都可以是任意字符串,因此在使用过程中一定要注意区分空格、双引号等字符。
创建数组
set student(name) “张三”;
set student(age) 15;
set student(gender) “男”;
查询数组
array size student;查询数组student中的元素个数
array names student;查询数组student的元素名称
多维数组
set grade(jim,chinese,english) [list 98 99];
set grade(peter,chinese,english) [list 96 100];
五、控制结构
控制结构有很多种类,包括条件、循环、异常处理、底层的条件处理等。
常见控制语句 | 解释 |
if {expression} {body1} else {body2}; if {expression1} {body1} elseif {expression2} {body2} | 条件执行语句,其中的else 或者else if并不是必须存在的 |
foreach value valuelist {body} | valuelist是一个链表数据,该命令将遍历valuelist中的每一个值,每遍历一次执行一边body |
switch $var {a {body1};b {body2};c {body3}} | 用一个值与很多模式比较,执行能匹配的那个模式所对应的body |
for {init} {test} {reinit} {body} | 将init作为初始量,将test作为表达式,如果为真则执行body,然后再讲reinit作为初始量重复执行该过程。 |
while {test} {body} | 将test作为表达式处理,如果其值为真,则执行body,然后再处理test重复这个过程 |
return | 结束一个函数返回value值 |
break | 用于终止最内层的循环 |
continue | 用于终止最内层循环的当前迭代步,进行该命令的下一个迭代步 |
catch {body} | 命令异常处理,当没有异常是返回值为0,否则返回非0值 |
六、程序结构
source :可以把一个外部的tcl文件在此处展开执行
global :指定某些变量是全局可用的。在tcl中,主程序里的变量并不是全局可用的,必须在出程序或过程里用global声明后,才能在过程里引用。
proc :说明一个子过程,后面接过程名、参数列表、执行体。需要注意的是,过程的参数列表应该和调用处的参数一致。但例外的是,如果过程的参数只写一个,它就可以以list的形式接收多个入口参数。
proc讲解:
1. 格式:proc name args body
2. 调用方法中参数可以用花括号或者双引号包含,也可以不包含
3. 在puts等命令中需要置换的话,需要使用方括号
例子:012_proc.tcl
proc sum {arg1 arg2} {
set x [expr $arg1+$arg2];
return $x ;#过程返回值
}
puts " The sum of 2 + 3 is: [sum 2 3]\n\n" ;#调用过程
#puts " The sum of 2 + 3 is: [sum {2 3}]\n\n" ;#出错,提示找不到第二个参数,置换过程中第一个参数是{2 3},所以找不到第二个参数
puts " The sum of 2 + 3 is: sum(2 3)\n\n" ;#输出sum(2 3),因为没有方括号,根本没有进行置换
puts " The sum of 2 + 3 is: sum{2 3}\n\n" ;#输出sum{2 3},因为没有方括号,根本没有进行置换
sum 2 3 ;#正确
sum {2} {3} ;#正确
sum "2" "3" ;#正确
过程PROC的参数定义
讲解:
1. 过程的参数赋缺省值:proc name {arg1 {arg2 value}}
2. 过程的不确定个数的参数定义:proc name {arg1 args}
proc example {first {second ""} args} { ;#参数定义:赋缺省值和不确定个数参数定义
if {$second == ""} {
puts "There is only one argument and it is: $first";
return 1;
} else {
if {$args == ""} {
puts "There are two arguments - $first and $second";
return 2;
} else {
puts "There are many arguments - $first and $second and $args";
return "many";
}
}
}
set count1 [example ONE]
set count2 [example ONE TWO]
set count3 [example ONE TWO THREE ]
set count4 [example ONE TWO THREE FOUR]
puts "The example was called with $count1, $count2, $count3, and $count4 Arguments"