Tcl parser 处理的特殊字符
 

相较於其他语言, Tcl 的基本语法规则非常简单, parser 只认得几个特殊字符.
参数分隔字符: (空格)
命令分隔字符: ;
可用以将数个命令放在同一列, 例如: puts hello ; puts world
注解字符: (放在一个命令最前面的) #
注意: 如何在同一列的左边写命令, 右边写注解?
set msg "hello, world!" ; # this is a comment
变量代换字符: $

为什麽在 简介 单元的范例中, set 後面的 msg 不要加 $, 而 puts 和 format 後面的 msg 要加 $ ? 因为 puts 和 format 对变量的名字没有特别的兴趣, 把所有参数当做字符串看; 而 set 则把参数当做变量的名字看. 究竟何时要把参数当做一般字符串, 何时要把参数当做变量的名字, 由各个命令自行决定. 大部分命令对变量的名字没有特别的兴趣, 他们之所以看起来像是可以处理变量, 完全是因为 parser 事先将 $... 代换过了.
删除变量: unset msg val
(当然, unset 对变量的名字有兴趣, 所以不要加 $)
数组变量代换字符: $...(...)

例: set days(jan) 31 ; set days(feb) 28 ; set days(mar) 31
之後可以这样用: format "There are %d days in Februrary" $days(feb)
数组的 "注标" 可以是任何字符串, 这在其他语言中叫做 associative array, hash, map, 或是 dictionary.
注意: $days(jan), $days(Jan), $days( jan) 是 days 数组中三个不一样的元素. 同样地, $dm(1), $dm(01), $dm( 1) 则是 dm 数组中三个不一样的元素.
所以 Tcl/Tk 中虽然没有多维数组, 我们还是可以用 "有规律的注标名称" 来达到相同的效果: set data(3,7) hello
在这里 3,7 整个被视为一个字符串.
看看一个数组内有那些 "注标" 有定义: array names days
注意: array names ... 传回的注标顺序没有什麽章法.
删除数组当中的一个元素: unset days(mar)
删除整个数组: unset days
命令结果代换 (command substitution): [ ... ]

题外话: 用 llength "how many words are there?" 可以计算字符串内有几个 "字" (即字符串被空格分割成几段)
假设 days 数组内 jan, feb, mar 等三个注标对应的元素有定义, 则 程序设计师下 llength [array names days] 时, parser 会先处理 [...], 最後 llength 这个命令接手时, 看到的命令是 llength jan feb mar
简单的 Tcl parser: 内定不代换 ("Quoting is the default!")
除了这些 (还有其他较少用的) 具有特殊意义的代换字符之外, 所有东西一律是字符串, 像是 + - * / < > ... 等等.
那麽数学运算式与逻辑运算式怎麽办呢? 用 expr 命令. expr 命令把它所有的参数串成一个很长的字符串, 然後当成一个数学/逻辑运算式来计算. (所以传给 expr 的参数有没有空格无所谓)
避免代换 (quoting)
\ 取消单一字符的特殊意义.
例: puts \$23.5
"..." 取消空格的意义.
例: puts "hello" 和 puts hello 效果完全一样;
但 puts "hello world!" 的双引号则不可省略.
{ ... } 取消空格的意义, 也取消所有代换. 试试看以下三例:
set x [expr 3 + 5]
set x "I have [expr 3 + 5] dollars. You have $x dollars."
set x {I have [expr 3 + 5] dollars. You have $x dollars.}

Q: {hello} 和 "hello" 有什麽不同? 提示: 查看手册 string(n), 用 string compare 比较字符串. (在 UNIX 命令行下打 man n string) Q: {puts} hello 和 puts {hello} 有什麽不同?
用 quoting 把程序 "冷冻" 成数据; 用 eval 命令 "解冻" 以执行程序:
set x [expr 3 + 5]
set x {expr 3 + 5}
eval $x

C 语言高手: qsort(3) 的 "把函数当做参数传递" 界面, 在 tcl 下应该更简单吧?
命令的传回值:
只有少数命令是用来印数据的, 例如 puts; 但是大部分命令都有传回值, 例如 set, llength, format, ... Tcl interpreter 在处理完一整列的命令後, 会把最後一个命令的传回值印出来. puts 只印数据, 没有传回值; 而 format 只有传回值, 不印数据. 所以在程序里面, 要把 format 出来的结果印出来, 必须和 puts 配合使用.
set x [puts hello]
puts $x
format "%x" 255; format "%x" 38; format "%x" 47
puts [format "%d decimal is %x hex" 255 255]

特殊字符的其他功能
输入键盘无法敲入的字符: \
例如 \a 为 "哔声" (0x7), \n 为换列 (0xa), \xhh 为 "ASCII 码是 0xhh 的字符".
把变量的值嵌在字符串当中: ...${...}...
例如 set middle "ma"; puts infor${middle}tion (这个功能可以用来动态产生变量名称)
奇怪的变量名称 (建议不要这样做!): ${...}
例如 set 名字 李大明; info vars; puts ${名字}
又如 set "max speed" 120; info vars; puts ${max speed}


 
作者:洪朝贵  (朝阳科技大学 信息管理系) 

©Tcl/Tk中文网 2003-2008
ALL RIGHTS RESERVED