TCL語言

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

變數

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

特殊數組

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輸入上取得數據,並存儲在某個變數中。

檔案句柄

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,則執行出錯。用來進行錯誤處理。

相關詞條

相關搜尋

熱門詞條

聯絡我們