- 2.1 脚本、命令和单词
- 2.2 处理命令
- 2.3 替换
- 2.4 引用
- 2.5 参数展开
- 2.6注释
- 2.7 正常返回与异常返回
Tcl的语法:决定如何解析命令的十多条规则。
2.1 脚本、命令和单词-
Tcl脚本: 包含一条或多条命令。命令通过换行符或分号隔开。
-
命令:
- 包含由一个或多个单词。单词通过空格或制表符分开。
- 第一个单词是命令名,其他单词是命令的参数。
-
Tcl 处理一条命令分两步:解析 和 执行。
注意:Tcl解析器在解析命令的时候,并不会为其中的单词赋予任何含义。这些单词的含义取决于具体的命令过程。
-
常见的参数的意义
expr 24 / 3.2
expr把参数连接成一个数学表达式。lindex {red green blue purple} 2
第一个参数是一个列表,值由空格隔开。 第二个参数为索引(从0开始),命令返回bluestring length helloworld
length 与 string length 组成集合命令,返回第二个参数的长度。button .b -text hello -fg red
.b(组件名)后面的参数为: -选项 值 。
-
Tcl的三种替换形式:
- 变量替换
- 命令替换
- 转义替换
-
注意:
- Tcl解释器在执行命令过程之前进行这些替换。
- [重要]解析命令时只从左到右解析一次,进行一轮替换。
- [重要]每一个字符只会发生一层替换,不会对替换后的结果再进行一次扫描替换。
- 替换可以发生在命令中的任何一个单词上,包括命令名。
- 替换不影响命令中每个单词的分隔。
-
变量替换 引发:
$
符号。 功能:将Tcl变量的值插入单词中。 变量名由$
符号后面所有的数字、字母和下划线组成。 例子:用变量替换新建组件.b1,.b2,.b3,.b4,.b5foreach num{1 2 3 4 5} { button .b$num }
-
命令替换 引发:
[]
符号 功能:把一个单词的部分或全部替换为一个命令的结果。[]
内的字符必须构成有效的Tcl脚本。 -
转义替换 引发:
字符替换结果\a警告音(0x7)\b删除(0x8)\f换页符(0xc)\n换行符(0xa)\r回车(0xd)\t制表符(0x9)\v垂直制表符(0xb)\ooo八进制值为ooo(1-3位)的8位Unicode字符\xhh十六进制位hh(前两位有效)的8位Unicode字符\uhhhh十六进制值为hhhh(1-4位)的16位Unicode字符\newline以及新行开头的空格一个空格字符\
符号 功能:转义字符 Tcl支持的转义字符:[注意]\newline和一般的替换不同,这种替换在Tcl解释器解析命令前就要单独进行。为了实现语句太长分行。
功能:为了阻止解析器对$
和;
等字符进行特殊处理。 除转义外的两种引用形式:
""
功能:取消其中的单词和命令分隔符的特殊解释。 说明:- 如果一个单词(字符串)的第一个字符是
"
,那么这个单词就由另一个"
标记结束。注意双引号本省不是单词的一部分,其中的空格、制表符、换行以及分号都作为普通字符处理。
set msg "Eggs: \$2.18/dozen\nGasoliine: \$1.49/gallon" # 执行结果: Eggs: $2.18/dozen Gasoliine: $1.49/gallon
- 如果单词不是以
"
开头,那么单词中的任何"
都会作为普通字符处理,而不是定界符。
puts This"is"poor"usage # 执行结果: This"is"poor"usage
- [注意]变量替换、命令替换和转义替换在双引号中正常进行。
set a 2.1 set msg "a is \"$a\": the square of a is \"[expr $a * $a]\" " # 执行结果: a is "2.1": the square of a is "4.41"
- 如果一个单词(字符串)的第一个字符是
{}
功能:取消其中所有特殊字符的特殊意义。 说明:- 如果一个单词以
{
开头,那么指导与它配对的}
为止,所有字符都将原封不动的识别位这个单词的值。 - 唯一会执行的替换:\newline,因为它先于解析器解析前替换。
- 大括号可以嵌套使用。
- 注意
{
与前一个单词需要用空格分隔。
执行过程:proc occur {value list} { set count 0 foreach el $list { if $el==$value { incr count } } return $count } occur 18 {1 34 18 16 18 72 1994 -3}
- 如果一个单词以
某些情况下,单层替换不能完成任务:
例子:删除所有txt类型的文件(1.txt、2.txt和3.txt三个文件) file delete [glob *.txt]
1. [glob *.txt]
的结果为:1.txt 2.txt 3.txt
2. 1.txt 2.txt 3.txt
作为一个整体传递给file delete(因为解析命令时只从左到右解析一次,进行一轮替换。),功能变成删除名为1.txt 2.txt 3.txt
的文件,发生错误。
如果一个单词以{*}
开头,之后紧接着非空白字符,Tcl会移除开头的`{*},把单词的剩余部分作为含有单词分隔符的语句进行解析替换,即重新替换一次。 [注意]只有Tcl 8.5版本以上支持
file delete {*}[glob *.txt]
等效于:
file delete 1.txt 2.txt 3.txt
对于Tcl 8.5更早的版本,用eval将这些单词重新传给Tcl解释器:
eval file delete [glob *.txt]
2.6注释
注释符#
必须出现在Tcl将获得命令的第一个字符上,其他地方将被挡住普通字符。
# 这是一条评论
set a 100 # 这不是一条评论
set a 100; # 这是一条评论
这将导致大括号内的注释常常会导致错误。
- 尽量避免在注释中出现大括号,如果确实要用,确保{}是成对的。
- 可以用
if 0 {}
实现大段格式正确的代码的注释
命令通常会返回字符串结果,但有时会返回错误,导致Tcl命令解释器放弃处理。 出现错误后,Tcl会把全局变量erroInfo
设置为一个栈,保存产生错误的确切位置。可以用puts $erroInfo
输出这个变量的值。