词条 | TCL语言 |
释义 | Tcl (最早称为“工具命令语言”"Tool Command Language", 但是目前已经不是这个含义,不过我们仍然称呼它为TCL)是一种 脚本语言。 由John Ousterhout创建。 TCL很好学,功能很强大。TCL经常被用于 快速原型开发,脚本编程, GUI和测试等方面。 基本概念Tcl (最早称为“工具命令语言”"Tool Command Language", 但是目前已经不是这个含义,不过我们仍然称呼它为TCL)是一种 脚本语言。 由John Ousterhout创建。 TCL很好学,功能很强大。TCL经常被用于 快速原型开发,脚本编程, GUI和测试等方面。TCL念作“踢叩” "tickle". Tcl的特性包括: * 任何东西都是一条命令,包括语法结构(for, if等)。 * 任何事物都可以重新定义和重载。 * 所有的数据类型都可以看作字符串。 * 语法规则相当简单 * 提供事件驱动给Socket和文件。基于时间或者用户定义的事件也可以。 * 动态的域定义。 * 很容易用C, C++,或者Java扩展。 * 解释语言,代码能够动态的改变。 * 完全的Unicode支持。 * 平台无关。Win32, UNIX, Mac 上都可以跑。 * 和Windows的GUI紧密集成。 Tk * 代码紧凑,易于维护。 TCL本身不提供面向对象的支持。但是语言本身很容易扩展到支持面向对象。许多C语言扩展都提供面向对象能力,包括XOTcl, Incr Tcl 等。另外SNIT扩展本身就是用TCL写的。 使用最广泛的TCL扩展是TK。 TK提供了各种OS平台下的图形用户界面GUI。连强大的Python语言都不单独提供自己的GUI,而是提供接口适配到TK上。另一个流行的扩展包是Expect. Expect提供了通过终端自动执行命令的能力,例如(passwd, ftp, telnet等命令驱动的外壳). 具体例子下面是TCL程序的例子: #!/bin/sh # next line restarts using tclsh in path \\ exec tclsh ${1+"$@"} # echo server that can handle multiple # simultaneous connections. proc newConnection { sock addr port } { # client connections will be handled in # line-buffered, non-blocking mode fconfigure $sock -blocking no -buffering line # call handleData when socket is readable fileevent $sock readable [ list handleData $sock ] } proc handleData { puts $sock [ gets $sock ] if { [ eof $sock ] } { close $sock } } # handle all connections to port given # as argument when server was invoked # by calling newConnection set port [ lindex $argv 0 ] socket -server newConnection $port # enter the event loop by waiting # on a dummy variable that is otherwise # unused. vwait forever 另外一个TK的例子 (来自 A simple A/D clock) 它使用了定时器时间,3行就显示了一个时钟。 proc every {ms body} {eval $body; after $ms [info level 0]} pack [label .clock -textvar time] every 1000 {set ::time [clock format [clock sec] -format %H:%M:%S]} ;# RS 解释:第一行定义了过程every, 每隔ms毫秒,就重新执行body代码。第二行创建了标签起内容由time变量决定。第3行中设置定时器,time变量从当前时间中每秒更新一次。 Tcl被广泛的用做script语言,大多数情况下,Tcl和Tk(“Tool Kit”)库同时使用,Tk是一系列令Tcl易于编写图形用户接口的命令和过程 Tcl的一个重要特性是它的扩展性。如果一个程序需要使用某些标准Tcl没有提供的功能,可以使用c语言创造一些新的Tcl命令,并很容易的融合进去。正是由于Tcl易于扩展,很多人为它编写了扩展包,并在网上共享。 Tcl和其他编程语言例如c不同,它是一种解释语言而非编译语言。Tcl程序由一系列Tcl命令组成,在运行时由Tcl解释器解释运行。解释运行的一个优点是它可以自己为自己生成Tcl script。 变量和变量交换不像c,Tcl的变量在使用前不需要声明。Tcl的变量在它首次被赋值时产生,使用set命令。变量可以用unset命令删除,虽然并不强制需要这样做。 变量的值通过$符号访问,也叫变量交换。 Tcl是一个典型的”弱类型定义”语言,这意味者任何类型可以存储在任何变量中。例如,同一个变量可以存储数字,日期,字符串甚至另一段Tcl script. Example 1.1: set foo "john" puts "Hi my name is $foo" Output: Hi my name is john Example 1.2: set month 2 set day 3 set year 97 set date "$month:$day:$year" puts $date Output: 2:3:97 Example 1.3: set foo "puts hi" eval $foo Output: hi 在这个例子里,变量foo存储了另外一段Tcl script. 表达式 包括数学表达式,关系表达式,通常用 expr命令。 Example 2.1: expr 0 == 1 Output: 0 Example 2.2: expr 1 == 1 Output: 1 两数比较,true则输出1,false输出0 Example 2.3: expr 4 + 5 Output: 9 Example 2.4: expr sin(2) Output: 0.909297 命令传递 以运算结果替代Tcl命令中的部分 Example 3.1: puts "I am [expr 10 * 2] years old, and my I.Q. is [expr 100 - 25]" Output: I am 20 years old, and my I.Q. is 75 方括号是命令传递的标志 Example 3.2: set my_height 6.0 puts "If I was 2 inches taller, I would be [expr $my_height + (2.0 / 12.0)] feet tall" Output: If I was 2 inches taller, I would be 6.16667 feet tall 命令流控制 Tcl有判断流转(if-else; switch)和循环控制(while; for; foreach) Example 4.1: set my_planet "earth" if {$my_planet == "earth"} { puts "I feel right at home." } elseif {$my_planet == "venus"} { puts "This is not my home." } else { puts "I am neither from Earth, nor from Venus." } set temp 95 if {$temp < 80} { puts "It's a little chilly." } else { puts "Warm enough for me." } Output: I feel right at home. Warm enough for me. Example 4.2: set num_legs 4 switch $num_legs { 2 {puts "It could be a human."} 4 {puts "It could be a cow."} 6 {puts "It could be an ant."} 8 {puts "It could be a spider."} default {puts "It could be anything."} } Output: It could be a cow. Example 4.3: for {set i 0} {$i < 10} {incr i 1} { puts "In the for loop, and i == $i" } Output: In the for loop, and i == 0 In the for loop, and i == 1 In the for loop, and i == 2 In the for loop, and i == 3 In the for loop, and i == 4 In the for loop, and i == 5 In the for loop, and i == 6 In the for loop, and i == 7 In the for loop, and i == 8 In the for loop, and i == 9 Example 4.4: set i 0 while {$i < 10} { puts "In the while loop, and i == $i" incr i 1 } Output: In the while loop, and i == 0 In the while loop, and i == 1 In the while loop, and i == 2 In the while loop, and i == 3 In the while loop, and i == 4 In the while loop, and i == 5 In the while loop, and i == 6 In the while loop, and i == 7 In the while loop, and i == 8 In the while loop, and i == 9 Example 4.5: foreach vowel {a e i o u} { puts "$vowel is a vowel" } Output: a is a vowel e is a vowel i is a vowel o is a vowel u is a vowel Procedures 参数定义方法Tcl的Procedures 和c的函数差不多. 它们有参数,它们返回值。基本定义方法是: proc name argList body 当一个procedure被定义,它就被看做是一个命令,如同Tcl的自带命令一样,通过名字来呼叫,名字后面跟上参数。 缺省的,procedure的返回值是它的最后一个命令结果。但也可以通过return命令来返回其他值。Return值可以在procedure的任何地方,一旦执行,procedure就此返回。 Example 5.1: proc sum_proc {a b} { return [expr $a + $b] } proc magnitude {num} { if {$num > 0} { return $num } set num [expr $num * (-1)] return $num } set num1 12 set num2 14 set sum [sum_proc $num1 $num2] puts "The sum is $sum" puts "The magnitude of 3 is [magnitude 3]" puts "The magnitude of -2 is [magnitude -2]" Output: The sum is 26 The magnitude of 3 is 3 The magnitude of -2 is 2 在procedure中可以通过set创造变量,但是变量只在procedure中有效,而且一旦procedure返回,这些变量就不可访问。如果procedure需要访问主程序中的变量,就需要使用global关键字。 Example 5.2: proc dumb_proc {} { set myvar 4 puts "The value of the local variable is $myvar" global myglobalvar puts "The value of the global variable is $myglobalvar" } set myglobalvar 79 dumb_proc Output: The value of the local variable is 4 The value of the global variable is 79 ListLists就好像是Tcl中的一种特殊的数组。它把一堆东西放成一个集合,然后就像操作一个整体一样的操作它。 Example 6.1: set simple_list "John Joe Mary Susan" puts [lindex $simple_list 0] puts [lindex $simple_list 2] Output: John Mary 注意list的index是从0开始的 Example 6.2: set simple_list2 "Mike Sam Heather Jennifer" set compound_list [list $simple_list $simple_list2] puts $compound_list puts [llength $compound_list] Output: {John Joe Mary Susan} {Mike Sam Heather Jennifer} 2 Example 6.3: set mylist "Mercury Venus Mars" puts $mylist set mylist [linsert $mylist 2 Earth] puts $mylist lappend mylist Jupiter puts $mylist Output: Mercury Venus Mars Mercury Venus Earth Mars Mercury Venus Earth Mars Jupiter Arrays Tcl数组在使用前无须定义,大小也不用指定。 Example 7.1: set myarray(0) "Zero" set myarray(1) "One" set myarray(2) "Two" for {set i 0} {$i < 3} {incr i 1} { puts $myarray($i) } Output: Zero One Two Example 7.2: set person_info(name) "Fred Smith" set person_info(age) "25" set person_info(occupation) "Plumber" foreach thing {name age occupation} { puts "$thing == $person_info($thing)" } Output: name == Fred Smith age == 25 occupation == Plumber 这个例子指出数组的index不需要是数字,其他类型的数据也可以。 Example 7.3: set person_info(name) "Fred Smith" set person_info(age) "25" set person_info(occupation) "Plumber" foreach thing [array names person_info] { puts "$thing == $person_info($thing)" } Output: occupation == Plumber age == 25 name == Fred Smith Strings 字符串是Tcl中最常用的类型,string有很多使用参数,可以参照Tcl手册。使用方法: string option arg arg ... Example 8.1: set str "This is a string" puts "The string is: $str" puts "The length of the string is: [string length $str]" puts "The character at index 3 is: [string index $str 3]" puts "The characters from index 4 through 8 are: [string range $str 4 8]" puts "The index of the first occurrence of letter \\"i\\" is: [string first i $str]" Output: The string is: This is a string The length of the string is: 16 The character at index 3 is: s The characters from index 4 through 8 are: is a The index of the first occurrence of letter "i" is: 2 Input/Output Tcl的绝大多数输入/输出是通过puts和gets做到的。Puts命令显示在console上,gets命令从console输入上取得数据,并存储在某个变量中。 gets channelId varNamechannelID可以理解为c的文件句柄,varName如果定义,输入值就赋给它,gets返回读入的字节数,否则gets直接返回输入值。 Example 9.1: puts -nonewline "Enter your name: " set bytesread [gets stdin name] puts "Your name is $name, and it is $bytesread bytes long" Output: (note that user input is shown in italics) Enter your name: Shyam Your name is Shyam, and it is 5 bytes long Example 9.2: set f [open "/tmp/myfile" "w"] puts $f "We live in Texas. It's already 110 degrees out here." puts $f "456" close $f Output: (none) Open打开了一个 "/tmp/myfile" 作为channel. 用法是: open name access access参数指出打开文件的方式,”w”是读写。这时可以用puts $f把内容写入文件 Example 9.3: set f [open "/tmp/myfile" "r"] set line1 [gets $f] set len_line2 [gets $f line2] close $f puts "line 1: $line1" puts "line 2: $line2" puts "Length of line 2: $len_line2" Output: line 1: We live in Texas. It's already 110 degrees out here. line 2: 456 Length of line 2: 3 这个例子假设已知文件只有两行,如果不是,则需要使用循环,用eof来找到文件尾。 eval eval命令会把它的参数直接送往解释器。 Example 10.1: set foo "set a 22" eval $foo puts $a Output: 22 单纯的执行$foo不会成功。 catch Example 10.2: set retval [catch {set f [open "nosuchfile" "r"]}] if {$retval == 1} { puts "An error occured" } Output: (this output occurs if there is no file named "nosuchfile" in the current directory). An error occured Catch 参数记录一个script的执行情况,如果返回值为1,则执行出错。用来进行错误处理。 |
随便看 |
百科全书收录4421916条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。