TCL语言

TCL语言【TCL语言】Tcl (最早称为“工具命令语言”"Tool Command Language", 但是目前已经不是这个含义,不过我们仍然称呼它为TCL)是一种 脚本语言 。由John Ousterhout创建 。TCL很好学,功能很强大 。TCL经常被用于 快速原型开发,脚本编程, GUI和测试等方面 。
基本介绍中文名:工具命令语言
外文名:Tool Command Language
简称:TCL语言
类别:脚本语言
基本概念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 modefconfigure $sock -blocking no -buffering line# call handleData whensocketis readablefileevent $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 newConnectionset 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 {msbody} {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 。参数定义Tcl的Procedures 和c的函式差不多. 它们有参数,它们返回值 。基本定义方法是:proc name argListbody当一个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 12set num2 14set 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 26The magnitude of 3 is 3The magnitude of -2 is 2在procedure中可以通过set创造变数,但是变数只在procedure中有效,而且一旦procedure返回,这些变数就不可访问 。如果procedure需要访问主程式中的变数,就需要使用global关键字 。Example 5.2:proc dumb_proc {} {set myvar 4puts "The value of the local variable is $myvar"global myglobalvarputs "The value of the global variable is $myglobalvar"}set myglobalvar 79dumb_procOutput:The value of the local variable is 4The value of the global variable is 79变数不像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 2set day 3set year 97set date "$month:$day:$year"puts $dateOutput: 2:3:97Example 1.3:set foo "puts hi"eval $fooOutput: hi在这个例子里,变数foo存储了另外一段Tcl script.表达式包括数学表达式,关係表达式,通常用 expr命令 。Example 2.1:expr 0 == 1Output: 0Example 2.2:expr 1 == 1Output: 1两数比较,true则输出1,false输出0Example 2.3:expr 4 + 5Output: 9Example 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.0puts "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 95if {$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 4switch $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 == 0In the for loop, and i == 1In the for loop, and i == 2In the for loop, and i == 3In the for loop, and i == 4In the for loop, and i == 5In the for loop, and i == 6In the for loop, and i == 7In the for loop, and i == 8In the for loop, and i == 9Example 4.4:set i 0while {$i < 10} {puts "In the while loop, and i == $i"incr i 1}Output:In the while loop, and i == 0In the while loop, and i == 1 In the while loop, and i == 2In the while loop, and i == 3In the while loop, and i == 4In the while loop, and i == 5In the while loop, and i == 6In the while loop, and i == 7In the while loop, and i == 8In the while loop, and i == 9Example 4.5:foreach vowel {a e i o u} {puts "$vowel is a vowel"}Output:a is a vowele is a voweli is a vowelo is a vowelu is a vowelProcedures特殊数组Lists就好像是Tcl中的一种特殊的数组 。它把一堆东西放成一个集合,然后就像操作一个整体一样的操作它 。Example 6.1:set simple_list "John Joe Mary Susan"puts [lindex $simple_list 0]puts [lindex $simple_list 2]Output:JohnMary注意list的index是从0开始的Example 6.2:set simple_list2 "Mike Sam Heather Jennifer"set compound_list [list $simple_list $simple_list2]puts $compound_listputs [llength $compound_list]Output:{John Joe Mary Susan} {Mike Sam Heather Jennifer}2Example 6.3:set mylist "Mercury Venus Mars"puts $mylistset mylist [linsert $mylist 2 Earth]puts $mylistlappend mylist Jupiterputs $mylistOutput:Mercury Venus MarsMercury Venus Earth MarsMercury Venus Earth Mars JupiterArraysTcl数组在使用前无须定义,大小也不用指定 。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:ZeroOneTwoExample 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 Smithage == 25occupation == 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 == Plumberage == 25name == Fred SmithStrings字元串是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 stringThe length of the string is: 16The character at index 3 is: sThe characters from index 4 through 8 are: is aThe index of the first occurrence of letter "i" is: 2Input/OutputTcl的绝大多数输入/输出是通过puts和gets做到的 。Puts命令显示在console上,gets命令从console输入上取得数据,并存储在某个变数中 。档案句柄channelID可以理解为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: ShyamYour name is Shyam, and it is 5 bytes longExample 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 $fOutput: (none)Open打开了一个 "/tmp/myfile" 作为channel. 用法是:open name accessaccess参数指出打开档案的方式,”w”是读写 。这时可以用puts $f把内容写入档案Example 9.3:set f [open "/tmp/myfile" "r"]set line1 [gets $f]set len_line2 [gets $f line2]close $fputs "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: 456Length of line 2: 3这个例子假设已知档案只有两行,如果不是,则需要使用循环,用eof来找到档案尾 。evaleval命令会把它的参数直接送往解释器 。Example 10.1:set foo "set a 22"eval $fooputs $aOutput:22单纯的执行$foo不会成功 。catchExample 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 occuredCatch 参数记录一个script的执行情况,如果返回值为1,则执行出错 。用来进行错误处理 。