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 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

  Lists

  Lists就好像是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 varName

  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: 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,则执行出错。用来进行错误处理。

你可能感兴趣的:(IT资料)