TCL基本语法
TCL基本语法 1.命令之间必须用换行或者分号隔开,单词之间必须用空格或 TAB 键隔开。 2.TCL 解释器对一个命令的求值过程分为两部分:分析和执行。在分析阶段,TCL 解释器运用规 则把命令分成一个个独立的单词,同时进行必要的置换(substitution); 在执行阶段,TCL 解 释器会把第一个单词当作命令名, 并查看这个命令是否有定义, 如果有定义就激活这个命令对应 的 C/C++过程,并把所有的单词作为参数传递给该命令过程,让命令过程进行处理。 3.赋值set,其有返回值,为所赋之值。 4.置换,分为变量置换,命令置换与反斜杠置换 .变量置换$, .命令置换[],它把随后的单词当作一个命令,eg:[expr 1+1]。[]里可以放多个命令,但是其返回值为最后一个命令的返回值。 .反斜杠置换,用于单词中插入特殊字符,比如空格,换行,[,$,以及C语言中的/n,/v等。 5.双引号及大括号 在双引号中各种分隔符不起作用,但是对换行符,及$,[]两种置换会起作用。而在大括号中,所以特殊字符将失去其特殊含义。 6.注释 在TCL解释器期望出现命令的地方出现的#到行末的部分被当作注释,eg:%#comment 或者 %set a b;#comment 7.变量 .变量最好按C/C++变量名要求,因为在置换时只把$往后第一个不是数字,字母,下划线的部分替换。当然,如果加上{}就另当别论了。 .TCL只支持关联数组。 8.相关命令 .set 赋值 .unset 它后面可以跟任意多个变量名,如果跟数组名则删掉整个数组。 .append 追加变量到一个文本型变量之后。 .incr 将一个数值加到一个整形变量上。 9.操作数 .与ANSI C一样。 10.数学函数 .expr arg?arg? 它把所有的参数组合到一起,作为一个表达式。 11.LIST .list可嵌套定义 .concat list?list? 将多个list连接成一个 .index list index 返回list中给定序号的元素,eg:index {1 2 {3 4}} 2,下标从0开始 .llength list 返回list的元素个数 .linsert list index value?value? 将一个list插入另一个list指定的序号处eg:linsert {1 2} 1 3 4 5 .lreplace list first last? value value ...?如果无value,则代表删除。 .lrange list first last 返回first到last之间的元素,如果last指定为end,则代表末尾。 .lappend varname value?value? 把所有给定的value加到varname的后面 .lsearch ?-exact?-glob?-regexp? list pattern 返回list中第一个匹配模式pattern的元素的索引,如果找汪以匹配就返回-1。-exact表示精确匹配,-glob的匹配方式和string match命令的匹配方式相同,-regexp表示正规表达式匹配。 .lsort options? list按照选项的方式进行排序 -ascii(default) -dictionary(不考虑大小写,有数字的话当作整数来排序) -integer -real -increasing -descreasing -command command .split string splitChars? 如果分隔符为一个空字符{},则按字符分开,如果没给出,则以空格为分隔符。 .join list joinString? 将list中所有元素合并到一个字符串中,中间以joinString分开,缺省的joinString是空格。 12.控制流 .if {test}{ ... }esleif { .. } 注意:执行体的{应该放在一行的末尾,否则TCL解释器会认为if命令在换行符处已结束,另外, if和{之间应该有一个空格,不然TCL解释器会把 if{作为一个整体当作一个命令名。 .while循环 .for循环,与C不同,它不用;隔开,而是用三个{}各自括起来。 .foreach 最基本的形式是foreach varName list body 也可以foreach varlist1 list1? varlist2 list2..?Body eg: set x {} foreach i {a b c} {j k} {d e f g}{ lappend x $i $j $k 执行过程如下: 1,i=a j=d k=e,x={a d e} 2,i=b j=f k=g,x={a d e b f g} 3,i=c j={} k={} x={a d e b f g c {} {} } .break continue .switch options?string{pattern body?patternbody?..} 第一个可选参数是options,表示进行匹配的方式,TCL支持三种匹配方式:-exact方式,-glob方式,-regexp方式,缺省情况表示-glob方式。 switch $x{ a - b {incr t1} c {incr t2} default {incr t3} } a后面的-表示使用与下一个模式相同的脚本。一旦switch命令找到一个模式匹配,就执行相应的脚本,并返回脚本的值,作用switch命令的返回值。 .eval arg? arg? ... 它可以接收一个或多个参数,然后把所有的参数以空格隔开组合到一起成为一个脚本,然后对这个脚本进行求值。eg:%eval set a 2; set b 4; .source 命令读一个文件并把这个文件的内容作为一个脚本进行求值。 source e:/tcl&c/hello.tcl 注意即使是在windows下,也应该使用UNIX下的/,而不是/ 13.过程 类似于C中的函数 %proc add{x y}{expr $x+$y} 也可以用return语句,也可以有默认的参数和可变参数,如果参数的最后一个为args,则代表可变参数,可以用foreach来取得。也有局部变量和全局变量之分,在过程外定义的即为全局变量,如果在过程内要使用全局就是,应使用global命令。 eg:%proc sample{x}{ global a incr a return [expr $a+$x]; } .upvar level? otherVar myVar?otherVar myVar...? 其作用相当于是指定别名,即引用。 level表示调用upvar命令的过程相对于我们希望引用的变量myVar在调用栈中相对位置。缺省为1。 14.文件 .open name ?access? access与我们熟悉的C语言类似,有r,r+,w,w+,a,a+ open 命令返回一个字符串用于表识打开的文件。TCL 有三个特定的文件标识:stdin,stdout 和 stderr ,分别对应标准输入、标准输出和错误通道,任何时候你都可以使用这三个文件标识。 gets fileId ?varName? 读 fileId 标识的文件的下一行,如果命令中有 varName忽略换行符。 就把该行赋给它,并返回该行的字符数(文件尾返回-1),如果没有 varName 参数,返回文件的下一行作为命令结果(如果到了文件尾,就返回空字符串)。 和gets类似的命令是read,不过 read 不是以行为单位的,它有两种形式: read ?-nonewline? fileId 读并返回 fileId 标识的文件中所有剩下的字节。如果没有 nonewline 开关,则在换行符处停止。 read fileId numBytes 在 fileId 标识的文件中读并返回下一个 numbytes 字节。 puts ?-nonewline? ?fileId? string puts 命令把 string 写到 fileId 中,如果没有 nonewline 开关的话,添加换行符。fileId 默认是 stdout。命令返回值为一空字符串。 puts 命令使用 C 的标准 I/O 库的缓冲区方案,这就意味着使用 puts 产生的信息不会立即出现 在目标文件中。如果你想使数据立即出现在文件中,那你就调用 flush 命令: flush fileId 把缓冲区内容写到 fileId 标识的文件中,命令返回值为空字符串。 flush 命令迫使缓冲区数据写到文件中。flush 直到数据被写完才返回。当文件关闭时缓冲区数 据会自动 flush。 close ?fileId? 关闭标识为 fileId 的文件,命令返回值为一空字符串。 OTCL 使用关键字Class定义一个类,eg:Class Animal TCL中的类有一些公共的行为,包括: .Alloc 创建一个新的实体。 .Create 如果没定义自己的Create函数,那么它是由默认的unknown过程调用的,其定义如下: Class instproc create {obj args} { set h [$self info heritage] foreach i [concat $self $h] { if {[$i info commands alloc] != {}} then { set args [eval [list $i] alloc [list $obj] $args] $obj class $self eval [list $obj] init $args return $obj } } error {No reachable alloc} } 从代码可知,它将沿着继承链创建相应的实例,并调用相应的init过程。 .info 此过程用于查询当前的一些状态信息,它有如下的选项: superclass 返回其父类列表 subclass 返回它的子类列表 heritage 返回它的继承列表 instances 返回属于此类的实体列表 instprocs 返回此类的过程列表 instcommands 返回所以的Tcl和c过程 instargs 返回Tcl过程的参数列表 instbody 返回Tcl过程的定义 instdefault 返回Tcl过程参数的默认值 .instproc为类添加成员函数,使用instvar为类添加成员变量。有一点需要注意的是,在一个函数中定义了成员变量,这虽然能保证此类中有这个成员变量,但是如果要在其他成员函数中使用,仍然要采用这种方式重新申明此成员变量。 eg: Animal instproc run {speed} { $self instvar speed set speed $speed puts "Animal run with speed $speed" } Animal instproc run2 {} { $self instvar speed puts "run2 run with speed $speed" } superclass 指定其父类,eg:Class Tiger -superclass Animal unknown 当没有匹配的方法时,它将被调用,一般会重载此函数,其默认实现如下,以完成Create: Class instproc unknown {m args} { if {$m == {create}} then { error "$self: unable to dispatch $m" } eval [list $self] create [list $m] $args }