Tcl 表示工具命令語言(Tool Command Language)

第一部分:TCL基本知識
一.簡介
Tcl 表示工具命令語言(Tool Command Language),它是一種流行的腳本編制語言,最初由加州大學伯克利分校的 John Ousterhout 教授開發。John Ousterhout 打算將 Tcl 作爲一種將其它程序組件粘合在一起的語言,既可以以同其它腳本語言相同的方式將 Tcl 用作交互式 shell/腳本解釋器,也可以將其作爲腳本解釋器嵌入您自己的 C 應用程序。在這種方式下,它就變成了一種向您自己的程序中添加腳本編制控制的方法,並且它提供了一些接口,這些接口允許您用自己的以 C 語言實現的腳本命令擴展基本 Tcl 語言.
Tcl 還有各種擴展,諸如 Tk,UI 工具箱,以及 Expect,Expect 是一種擴展,用於自動化同其它基於 shell 的命令(例如 telnet 和 ftp)的交互。
Tcl是一種很通用的腳本語言,它幾乎在所有的平臺上都可以解釋運行,功能強大。
Tcl包含了兩個部分:一個語言和一個庫。
  首先,Tcl是一種簡單的腳本語言,主要使用於發佈命令給一 些互交程序如文本編輯器、調試器和shell。它有一個簡單的語法 和很強可擴充性,Tcl可以創建新的過程以增強其內建命令的能力。
其次,Tcl是一個庫包,可以被嵌入應用程序,Tcl的庫包含了一個分析器、用於執行內建命令的例程和可以使你擴充(定義新的 過程)的庫函數。應用程序可以產生Tcl命令並執行,命令可以由用戶產生,也可以從用戶接口的一個輸入中讀取(按鈕或菜單等)。 但Tcl庫收到命令後將它分解並執行內建的命令,經常會產生遞歸的調用。
腳本語言的優勢:
快速開發:腳本語言極大地簡化了“開發、部署、測試和調試”的週期過程。  
容易部署:大多數腳本語言都能夠隨時部署,而不需要耗時的編譯/打包過程。  
同已有技術的集成:腳本語言被Java或者COM這樣的組件技術所包圍,因此能夠有效地利用代碼。  
易學易用:很多腳本語言的技術要求通常要低一些,因此能夠更容易地找到大量合適的技術人員。  
動態代碼:腳本語言的代碼能夠被實時生成和執行,這是一項高級特性,在某些應用程序裏(例如JavaScript裏的動態類型)是很有用也是必需的。  

二.TCL的語法規則
1.解釋器
  在Tcl的數據結構中的核心是Tcl_Interp.一個解釋器包含了一套命令,一組變量和一些用於描述狀態的東西。每一個 Tcl命令是在特定的Tcl_Interp中運行的,基於Tcl的應用程序可以同時擁有幾個Tcl_Interp。Tcl_Interp是一個輕量級的結構,可以快速的新建和刪除。
2.數據類型
  Tcl只支持一種數據結構:字符串(string)。所有的命令,命令的所有的參數,命令的結果,所有的變量都是字符串。請牢記這一點,所有的東西都是字符串。 這是它比較有特點的方面字符串有三種形式:命令(command), 表達式(expresion)和表(list)。
三.TCL基本語法
1.tcl命令
一條tcl命令的基本語法爲:
command arg1 arg2 arg3
其中command可以是內建過程也可以是用戶建的新命令,如果是用戶用戶建的新命令應用程序中用函數Tcl_CreateCommand來創建。所有的參數作爲字符串來傳遞,命令自己會按其所需來解釋的參數的。命令的名字必須被打全,但 Tcl解釋器找不到一同名的命令時會用 unknown命令來代替。;
空格符用來分隔命令名和他的變元,換行符或者分號用來表示一條命令的結束.
    例如:
set a 22 //相當於C中的 a=22 a是一個變量這條命令分爲三個域:1: set    2: a    3: 22
set使用於設置變量的值的命令,a、20 作爲參數來傳給它,a使它要操作的變量名,22是要付給的a值。
2.註釋
和shell很象,第一個字母是"#"的Tcl字符串是註釋。
3.變量
   set命令用於將值賦給變量.它接受2個變元:第一個是變量名,第2個是值.變量名可任意長,並且可區分大小寫;
在使用變量前無須對tcl變量進行聲明;
可以通過美元符號語法來獲取變量的值.
4.數字表達式
  tcl解釋器本身不對數學表達式進行計算,tcl只是完成分組,替換和命令的調用工作,而expr命令用來對數字表達式進行分析和計算.
5.替換和分組
5.1 在變量裏面提到過的使用$符合來完成替換
5.2命令替換
當命令的一個子域以方括號開始以方括號結束,表示要進行一個命令子替換。並執行該子命令,用其結果來替換原命令中的方括號部分。方括號中的部分都被視爲Tcl命令。
例如:
    set a [set b "hello"]
  實現執行 set b "hello" 並用其結果來替換源命令 中的方括號部分,產生一條新命令
  set a "hello" //"hello" 爲 set b "hello" 的返回值
最終的結果是b="hello" a="hello"
  方括號沒有分組作用
5.3反斜槓替換
用來引用對解釋器來說具有特殊意義的字符,比如:你可以通過反斜槓引用形式指定一個純粹的美元符合,花括號或者方括號.
如:set dollar /$foo
=>$foo
5.4 使用花括號和雙引號進行分組
雙引號和花括號被用來將多個單詞組織成一個變元.雙引號和花括號之間的差別就是,雙引號允許在分組重出現替換操作,而花括號則會阻止這種替換的發生.這種規則適用於命令,變量和反斜槓替換.
如:set s hello
=>Hello
puts stdout "The length of $s is [string length $s]"
=>The length of Hello is 5
   puts stdout {The length of $s is [string length $s]}
=>The length of $s is [string length $s]
5.5 分組在替換前進行
TCL語法分析器只對命令執行一遍分組和字符串替換操作.分組決定是在替換前完成的,這是TCL的一種很重要的屬性,它表明經過替換的值並不影響分組結果,因爲分組決定已經作出了.
例如:
set x 7;set y 9
puts student $s+$y=[expr $x+$y]
=>7+9=16
四.總結
一. 命令綜述
  1.一個命令就是一個字符串(string)。
  2.命令是用換行符或分號來分隔的。
  3.一個命令由許多的域組成。第一個於是命令名,其它的域作爲參數來傳遞。
  4.域通常是有空白(Tab橫向製表健 Space空格)來分開的。
  5.雙引號可以使一個參數包括換行符或分號。三種子替換仍然發生。
  6.花括號類似於雙引號,只是不進行三總體換。
  7.系統只進行一層子替換,機制替換的結果不會再去做子替換。而且子替換可以在任何一個域進行。
8.如果第一個非控字符是`#", 這一行的所有東西都是註釋。
二.替換和分組
下面的規則總結了TCL解釋器在調用一條命令之前所完成的基本分組和替換機制:
 命令變元以空白符加以分隔,除非他們像下面所描述的這樣使用花括號或者雙引號進行分組.
 使用花括號,{},進行分組會阻止替換操作.括號可以嵌套.解釋器將會在分組中包括所有匹配左右括號之間的字符,其中包括換行符、分號和嵌套括號.用於分組的花括號(即,最外層的花括號)不包含在分組值中.
 使用雙引號,””,進行分組允許替換操作.解釋器會將所有的內容包括在內,直到碰到另一個雙引號爲止,其中包括換行符和分號.分組用的雙引號不包括在分組字符當中.可以通過反斜槓引用(如/”)將雙引號包括在分組中.
 分組決定是在替換之前作出的.這也意味着變量值或者命令結果並不影響分組.
 美元符號,$,將會導致變量替換.變量名可以任意長,而且區分大小寫.如果變量引用嵌套在其他字符串中,或是其中包含了除字母、數字和下劃線之外的其他字符,那麼可以通過${varname}的語法形式加以區分.
 方括號,[],將會導致命令替換.括號中的內容都被當作一條命令看待,而且包括方括號在內的所有內容都將替換成命令的結果.這是嵌套是允許的.
 反斜槓字符,/,用來引用特殊的字符.你可以認爲這是另外一種形式的替換,這裏反斜槓與後面的一個或一組字符將被替換成一個新字符.
 替換操作可以發生在任何地方,除非使用花括號加以阻止.分組中的一部分可以是常量字符串,而別的部分又可以是替換所產生的結果,甚至命令名都可以受到替換的影響.
 在調用命令之前只完成一遍替換,不再對替換結果進行第2遍解釋.這條規則在你的變量值或命令結果中包含諸如空格、美元符合、方括號或花括號等特殊字符時就顯得非常重要.因爲子進行一遍替換操作,所有你不必擔心這些值中得特殊字符會導致額外得替換.
三.使用FAQ
 一種常見的錯誤就是在使用花括號或雙引號進行分組時忘記在變元之間插入空格符.因爲空白符用作變元的分隔符,而花括號和引號只提供分組的功能.如果你忘記了這些空格符,就會出現”在封閉花括號或者雙引號之後發現非期望字符”之類的錯誤.由於}與{直接缺少空格,所有下面的代碼就是錯誤的:
if {$x > 1}{puts “x=$x”}
 雙引號只有在空白符之後出現時才被用於分組,這也就是說你可以將雙引號包含在一個分組當中而無須使用反斜槓引用.這要求要有花括號或空白符來界定這個分組.不推薦使用這種晦澀難懂的功能
 當使用雙引號進行分組時,花括號的特殊作用將被關閉.替換會在雙引號擴起來的分組中的任何地方發生.下一條命令中,變量仍然被替換了
如:set x xvalue;set y “foo {$x} bar”;
=> foo {xvalue} bar
 當使用雙引號進行分組時,其中的內嵌命令仍然可以使用雙引號進行分組.
put “result [format “%f %f” $x $y]”
 用做命令替換的方括號之間的空白符不是必須的.出於分組的考慮,解釋器會把方括號之間的任何內容都作爲當前分組的一部分.下面的代碼將x設置爲兩條命令結果的連接,原因就是]和[之間沒有空格.
set x [cmd1][cmd2]
 當使用花括號或雙引號進行分組時,換行苻和分號可以被忽略.他們會像其他字符一樣包括在分組字符中.下面的代碼將x設置爲包含換行符的字符串:
set x “this is line one”
this is line two.
this is line three.
 在進行命令替換過程中,換行符與分號的作用就是作爲命令終止符.如果你有一條很長的嵌套在方括號中的命令,而且想在另一行上繼續這條命令的話,就請在換行符前插入一個反斜槓.這在例1-9中已有示範.
 當一個美元符號後面跟的是除字母、數字、下劃線或左小括號之外的其他內容時,它就會被當作一個純粹的美元符號.
第二部分:JACL介紹
一.Jacl簡介:
Jacl 是流行的 Tcl 腳本語言的 Java 實現。使用 Jacl,您可以在 XML 或 XSL 中嵌入用腳本編寫的功能。此外,由於其 Java 擴展,因此,您可以使用 Jacl 來同基於 Java 的 Apache 工具內的 Java 對象進行交互
Jacl 向 Java 開發人員提供了另外一種處理 XML 的方法。Jacl 是流行的腳本語言 Tcl 的一種 Java 實現,使用它您可以深入底層並向使用 Ant 編寫的 XML 構建或使用 Xalan 和 Cocoon 生成的轉換中添加功能。
    除了實現大多數 Tcl 命令集之外,Jacl 還提供了一些其自己的 Tcl 命令,這些命令允許程序員同 Java VM 交互。這些額外的命令允許 Jacl 代碼創建 Java 對象,調用其中的方法,調用靜態方法,內省 Java 對象甚至將 Jacl 偵聽器綁定到 Java 事件。這種在同一個腳本中同時使用 Tcl 和 Java 代碼的能力帶來了許多可能性。試想爲系統編寫一套 Java 服務、組件或構件塊。通過在同這些組件相同的 VM 中使用 Jacl,您可以以腳本方式執行和控制 Java 組件。

     您也可以使用 Jacl 作爲交互式 shell,在那裏您可以以交互方式(也就是從通常的 shell 提示符中)創建 Java 對象並調用其中的方法
Jacl 是 Tcl 解釋器的 Java 實現:無須安裝 Tcl 解釋器,您僅需一個 Java VM 以及相關的 Jacl jar 文件。Jacl 通過其 Java 特性提供了一種真正的跨平臺的腳本語言
對於習慣了 Java 而又不想投入太多時間學習另外一種語言的程序員來說,Jacl 也是一種非常強大的通用腳本語言。Tcl 有相對清晰和簡單的語法,Java 程序員可以以混合然後匹配的方式使用 Jacl:將 Jacl 用於那些腳本語言最適用的地方(簡單文件處理、正則表達式解析、字符串替換、執行系統命令等等),並利用 Jacl 的 Java 擴展來訪問完整的 Java API 以及重用現有的 API 知識。
二.Jacl安裝
下載 jacl1.2.6 源代碼壓縮文檔,解壓縮/壓縮/tar 該分發版,然後執行 README 中的構建指令。一旦配置並構建了 jacl,您將在平臺構建目錄內發現兩個 jar 文件,jacl.jar 和 tcljava.jar。要在 UNIX 平臺上運行交互式 Jacl shell,請運行 UNIX 平臺構建目錄下的 jaclsh。如果您運行的是 Windows,請使用清單 2 中的批處理文件。

您的環境必須將 jaclsh 文件的位置包含在其 PATH 裏,並將兩個 jar 文件包含在 CLASSPATH 裏。(您甚至想要將 jaclsh 複製或符號鏈接到 /usr/local/bin。)

現在可以使用 Jacl 了
第三部分.TCL內建函數對字符串的處理
這部分主要描述有關字符串操作和簡單模式匹配的內容.主要介紹的命令有:
1. string
2. append
3. format
4. scan
5. binary
字符串是tcl中的基本數據項,因此有大量用來操作字符串的命令並不奇怪.一個與之密切相關的主題就是模式匹配,其中通過將字符串與模式進行匹配可以是字符串的比較功能更強大.
一.string命令:
string命令實際上是一組操作字符串的命令,string的第一個變元決定了進行什麼樣的操作,如下面的例子計算得到一個變量值的長度:
set name “brent welch”
string length $name
=> 11
常用的字符串操作有
 equal操作
用法爲:string equal?-nocase?str1 str2
 字符串match
用法爲:string match pattern str
 大小寫轉換操作
tolower 、totitle及toupper.用法爲:string tolower string ?first?last?
 字符串清理操作
trim、trimright和trimleft.用法爲:string trim string ?chars?
 將string分裂成列表。缺省以空白爲分隔符,也可通過splitChars來設定分隔符
split string ?splitChars?
 執行字符串的比較,按 C strcmp 的方式。返回 -1, 0, or 1。
string compare string1 string2
 在string1種查找string2的定義次出現的位置。未找到返回-1
string first string1 string2
 返回字符串string的長度
string length string
 判斷string是否能匹配pattern。pattern是以shell文件名的統配格式來給出
string match pattern string
 返回字符串string中從first到last之間的內容
string range string first last
 將string轉換爲小寫
string tolower string
 將string轉換爲大寫
string toupper string
 將string的左右空白去掉
string trim string
 將string的左空白去掉
string trimleft string
 將string的右空白去掉
string trimright string
FAQ:
使用expr來進行字符串匹配不可靠,建議不要使用,安全的比對方法爲使用string compare和equal操作來進行字符串比對
 string is命令用來測試一個字符串是否屬於某個特定的類.
 srting map命令根據字符映射對字符串進行轉換,映射以輸入、輸出形式表示.
例如:sring map “food” {f p d 1}
          =>pool
二.append命令
append varName value
append varName value value value ...
   append命令接收一個變量名作爲它的第一個變元,並把剩餘的變元連接到該指定變量當前值的後面.這個變量如果事先不存在就會被創建
  
FAQ:
對於大字符串來說,addend命令很有效率
例如:
append i "some new stuff" 就比下面的方式速度快
set i " some new stuff "
三.format命令
format命令與C語言中的printf函數類似,它根據一種格式說明來格式化字符串:
format spec value1 value2....
spec變元包括文字和關鍵詞.文字將原封不動地存在到結果中,而每個關鍵字會指示如何格式化對應的變元.使用百分號(%)來引入一個關鍵字,其後跟着0個或多個修飾符並使用一個轉換限定符作爲結尾.關鍵字的例子包括用於浮點數的%f、用於整數的%d以及用於字符串格式的%s.使用%%可以獲取一個單一的百分號.對於每個變元來說,最爲通用的關鍵字說明可以包括多達6個部分:
 位置說明符
 標誌
 字段寬度
 精度
 單詞長度
 轉換字符
四.scan命令
scan命令根據格式規範描述來解析一個字符串並把值賦給變量.它返回成功完成的轉換格式.該命令的通用形式爲:
scan string format var ?var? ?var?....
scan中的格式幾乎與format命令中的完全相同.不存在掃描格式%u.描述格式%c會將一個字符轉換成它的十進制值.
scan格式包含有一種集合的概念.它使用方括號來界定一組字符.這個集合匹配拷貝到變量中的一個或多個字符.它使用橫槓來指定一個區間.下面的例子掃描一個全部以小寫字母組成的字段
scan abcABC {%[a-z]} result
=>1
set result
=> abc
五.binary命令
binary命令用於字符串和壓縮的二進制表示形式之間的轉換.binary format命令接收數值並根據模板進行壓縮.例如:她可以用來在內存中格式化一個適合傳遞給fortran的浮點向量.最終的二進制值被返回:
binary format template value ?value...?
binary scan命令根據類似的模板從二進制字符串中獲取數值.這對獲取以二進制格式存儲的數據來說非常有用.它將值賦給一組TCL變量
binary scan value template variable ?variable ...?
第四部分.TCL列表
這部分主要描述有關TCL列表的內容.主要介紹的命令有:
 list
 lindex
 llength
 lrange
 lappend
 linsert
 lreplace
 lsearch
 lsort
 concat
 join
 split
TCL列表是一系統的值.當你輸出一個列表時,它擁有與TCL命令相同的語法.列表使用空白符將元素分割開來.可以使用花括號或雙引號將包含空白符的單詞組成一個單一的列表元素
一.list命令
   list命令根據它的變元來構建一個列表,因此列表的每個元素都是一個變元.如果某個元素包含有特殊字符,list命令將會添加引用以確保它們被解析爲結果列表中的單一元素.
例如:
set x {1 2}
=>1 2
set y foo
=>foo
set L1 [list $x “a b” $y]
=> {1 2} {a b} foo
set L2 “/{$x/} {a b } $y”
=>{1 2} {a b} foo

FAQ
list命令將會自動完成引用,對比上述例子L1和L2.
二.lappend命令
lappend命令用於將元素添加到列表末尾.
例如:
lappend new 1 2
=> 1 2
lappend new 3 “4 5”
=> 1 2 3 {4 5}
set new
=>1 2 3 {4 5}
三concat命令
concat命令適用於將列表拚裝到一起.它將變元連接起來,其間用空格分開.這樣多個列表會合併成一個列表,每個輸入列表中的頂層列表元素會成爲結果列表中的頂層列表元素.
例如:
set x {4 5 6}
set y {2 3}
set z 1
concat $z $y $x
=> 1 2 3 4 5 6
FAQ
1. 雙引號和concat的區別
對於簡單情況,雙引號就像concat一樣工作.然而,concat命令會先去除其變元末尾的多餘空白符,然後才使用一個單一的空格符將他們連接起來
2. concat和list的區別
當冬天建立tcl命令時,list於concat之間的差異就顯得重要起來.基本規則就是list和lappend保留列表的結構,而concat(或雙引號)則會消除一層列表結構.由於存在list與concat返回相同結果的例子,這種差異就顯得很微秒.不幸的是,這樣會導致產生依賴於數據的錯誤.
例子:雙引號與concat和list命令的比較
set x {1 2}
    => 1 2
   set y “$x 3”
   =>1 2  3
   set y [concat $x 3]
   => 1 2 3
  set s { 2 }
  => 2
  set y “1 $s 3”
  => 1 2 3
  set y [concat 1 $s 3]
=> 1 2 3
set z [list $x $s 3]
=> {1 2} { 2 } 3
四.獲取列表元素
一.llength命令返回列表中元素的個數.
如:llength {a b {c d} “e f g” h}
=>5
llength{ }
=> 0
二.lindex命令返回列表中的一個特定元素.它接收一個索引; 列表的索引從0開始記數.
如:set x {1 2 3 }
 lindex $x 1
 => 2
還可以使用關鍵字end來指定列表的最後一個元素,或是使用語法end-N從列表的末尾倒記數.
三.lrange命令
lrange命令返回一個區段的列表元素.一個一個列表及兩個索引爲變元,可以使用end和end-N作爲索引
五.修改列表
一.linsert命令在列表值中指定的索引位置插入一個元素.如果索引爲0或者更小,那麼元素就會添加倒列表值的前面.如果索引等於或者大於列表的長度,元素則被追加倒尾部.
二.lreplace命令將一個區段的列表元素替換爲新的元素.如果沒有指定任何新的元素,那麼它就會從列表中刪除這些元素.
FAQ
linsert命令和lreplace命令並不對現有報表進行修改,而是返回一個新的列表值.如下面例子
使用linsert和lreplace修改列表
linsert {1 2} 0 new stuff
=> new stuff 1 2
set x [list a {b c} e d]
=> a {b c} e d
lreplace $x 1 2 B C
=> a B C d
lreplace $x 0 0
=> {b c} e d
六.搜索列表
lsearch命令返回列表中的一個值的索引,如果值不在就返回-1
七.對列表進行排序
使用lsort命令以多種方式對列表進行排序.lsort並不是對原表進行排序,而是返回一個新的列表,可以通過-ascii、-directory、-interger或-real選項來指定基本的排序類型,可以通過選項-increasing或-decreasing指定排序方式,默認選項設置爲: -ascii –increasing.
例如: lsort –ascii  {a  Z  n2  n100}
=> Z  a  n100  n2
lsort  -dictionary  {a  Z  n2  n100}
=> a  n2  n100  Z
八.split命令
   split命令接收一個字符串,並根據指定的字符將其分割轉換爲一個列表,同時保證其結果具有恰當的列表語法.
例如:set line  {welch:*:28405:100:Brent  Welch:/usr/welch:/bin/csh}
split  $line :
=> welch * 28405 100  {Brent  Welch}  /usr/welch  /bin/csh
lindex  [split $line :]  4
=> Brent Welch

FAQ
不要對任意數據都使用列表操作
既便你的數據中包含有空格分隔的單詞,你也應當對任意的輸入數據小心使用列表操作.否則,輸入中零散的雙引號或者花括號會在腳本中產生無效列表結構和錯誤.
九.join命令
join命令作用和split正好相反,它接收一個列表值並使用指定的分隔列表元素的字符對其重新進行格式化.
例如:
join  {1  {2  3}   {4  5  6 }}
=> 1:2  3:4  5  6
第五部分:控制結構命令
   TCL中的控制結構是通過使用命令來實現的,這些命令中包括循環命令:while、foreach和for,包括條件命令:if和switch,包括錯誤處理命令:catch,還包括一些用於微調控制結構的命令:break、continue、return和error.
一.If Then Else控制命令
   if expression ?then? body1 ?else? ?body2
   例如:
   if {$x  = =  0}{
      puts stderr “divide by zero!”
} else {
  set slope [expr $y/$x]
}
 FAQ:
花括號的位置非常重要
如if $x break continue 建議改爲如下風格:
         if { $x } {
           break
          } else {
            continue
          }
二.switch控制命令
switch命令根據命令表達式值的不同分別執行多個分支命令體中的一個.該命令的一般形式爲:
   switch  flags  value  pat1  body1  pat2  body2
  可以指定任意數量的模式 – 命令體對.如果匹配多個模式,那麼只需要計算第一個匹配模式的命令體,也可以將所有的模式 – 命令體組織倒一個變元中.
  switch flags value { pat1 body1  pat2  body2........}
三while控制命令
while命令接收2個變元: 一個測試表達式和一個命令體,如下:
while booleanExpr body
FAQ
while命令反覆對布爾表達式進行測試,如果表達式爲真(非 0) 就執行命令體.由於在每次循環之前都要重新計算測試表達式的值,因此保護表達式使之免於在while命令被調用以前發生任何替換操作非常關鍵.下面就是一個無限循環的例子:
set i 0; while $i <10 {incr i}
下面的代碼纔是正確的
set i 0 ;while {$i<10} {incr i}
四.Foreach命令
 Foreach命令循環執行一個命令體,每次將一個或多個列表中的每個值賦值給一個或多個循環變量.該命令的語法如下:
   foreach loopVar valueList commandBody
 Foreach名字支持多個循環變量.假設有2個循環變量x和y,在第一次循環中,x從值列表中獲取第一個值,而y獲取第二個值,在第2次循環中,x獲取第3個值,而y獲取第4個值,這樣一直持續到不在有值爲止.如果沒有足夠的可賦給所有循環變量的值,多餘的變量將會以空字符串作爲它們的值.
 Foreach支持多個值列表.Foreach可以同時對多個值列表進行循環操作.在這種情況下,每個值列表還可以包含一個或多個變量.foreach將一直循環執行直到所有值列表中的所有值都被使用過爲止.如果在最後一次循環之前就用盡了一個值列表中的值,那麼與之對應的循環變量就會以空字符串來作爲他們的值.
六.for命令
for命令與c語言中的for語句相似,接收4個變元:
for  initial  test  final  body
七.Break與Contiune
可以通過break和contiune命令來控制循環的執行.break命令會導致立刻從循環中退出,而contiune命令則會是循環繼續進行下一個迭代,tcl中沒有goto命令.
八Catch
在實際應用中,如果一條命令在調用時使用了錯誤的變元數目或是根據自身的實現檢測出了某種錯誤,它就會報錯.一個沒有捕獲的錯誤將會終斷腳本的執行.catch命令就是用來捕獲這種錯誤的,它接收2個變元:
   catch  command ?resultVar?
 catch的第一個變元是命令體.第2個變元是一個變量名,它包含命令的結果,或是在命令報錯時的一條錯誤信息.如果沒有捕獲任何錯誤,catch就會返回0,如果捕獲到了錯誤就返回一個非零的錯誤代碼.
 應當使用花括號而不是雙引號來將命令括起來,這是因爲catch將會調用完整的TCL解釋器來解釋命令.如果使用雙引號,那麼在調用catch之前就會發生又一輪的替換操作,最簡單的catch用法就像下面這樣:
catch {command}
 catch命令的捕獲不僅僅是錯誤,如果命令體中包含有return、break或contiune命令的話,它們將會終止命令體並被catch以非0的返回代碼反映出來.
九.Error命令
除非使用catch命令進行捕獲,否則error命令將會報告一個錯誤狀態並終止腳本的執行,該命令最多可以接收三個變元:
error message
error message info
error message info code
  message返回一個錯誤,引起解釋器停止運行。info用於初始化全局變量errorInfo。code被付給errorCode。
十.Return命令
return命令用來從過程中返回,還可以使用return的一些可選變元來指定異常的返回狀態,完整語法如下:
return  ?code  c?-errorinfo i?  ?-errorcode  ec?  string
 -code選項是ok、error、return、break、contiune中的一個,也可以是一個整數,如果沒有指定-code,默認就是ok
 code error選項似的return的行爲非常類似與error命令.-errorcode選項設置全局變量errorcode,而-errorinfo選項則初始化全局變量errorinfo.當使用return –code error是,在堆棧狀態中就不會有error命令.
第六部分:過程與作用域
過程封裝了一組命令併爲變量引入了一種局部作用域.
一.proc命令
TCL過程由proc命令來定義,接收三個變元:
proc name params body
 第一個變元爲過程名,它會增加到tcl解釋器所識別的命令集中.過程名區分大小寫而且可以包含任意字符,過程名並不與變量名衝突
 第二個變元是一個包含參數名的列表.
 第三個變元是一個過程體

FAQ
使用rename來改變命令
rename命令用來改變命令的名字.其用途有2個
 對現有過程進行擴充,並保留老命令的透明性.
 通過更改命令名稱可以完全隱藏一條命令.
二.global命令
全局作用域爲頂層作用域,該作用域處於任何過程之外,必須通過global命令才能在過程內部使用在全局作用域中定義的變量.global的語法爲:
global varName1 varName2......
FAQ:
global命令存在於過程內部.

三upvar命令
當需要將變量名二不是他的值傳遞給過程的時候,就藥使用vpvar命令.upvar命令將一個局部變量與沿Tcl調用棧向上一層作用域中的變量關聯在一起.upvar命令語法爲:
upvar  ?level1?  varName  localVar
第七部分:TCL數組
一. array命令
 array命令返回有關數組變量的信息.
 array names命令返回數組中定義的索引名,如果沒有定義數組變量,那麼array names就會返回一個空列表
 array get和array set操作用來在數組和列表間進行轉換.array get返回的列表包含偶數個數的元素,第一個元素是索引,下一個是對應的數組值,剩下的列表元素交替爲索引和值.array set的列表變元必須要有同樣的結構.
array命令參數極其相關的命令參見下面例子:
 一組用於向量操作的命令。第二個參數是子命令名
array subcommand arrayName
array subcommand arrayName arg ...
  假設:
set a(1) 1111
set a(2) 2222
set a(three) 3333
  一下均以它爲例子(tclsh在中運行)。
 返回一個數組元素名字的列表
array names arrayName
例如:
tclsh>array names a
1 2 three
 返回數組的元素個數
array size arrayName
例如:
tclsh>array size a
3
 用於遍歷的命令
arrry startsearch arrayName
初始化一次遍歷,返回一個遍歷標示(searchId)在下面的命令是中使用。

 返回下一個數組中的元素。如果沒有返回一個空串。
array nextelement arrayName searchId
 返回 1 表示還有更多的元素。0 表示沒有了。
array anymore arrayName searchId
結束該次遍歷。
array donesearch arrayName searchId
  返回下一個元素。
array nextelement arrayName searchId
例如:
tclsh>array startsearch a
s-1-a
tclsh>array nextelement a s-1-a
1111
tclsh>array nextelement a s-1-a
2222
tclsh>array anymore a s-1-a
1
tclsh?array nextelement a s-1-a
3333
tclsh>array donesearch a s-1-a
  注意可以同時併發多個遍歷。
第八部分:對文件和程序的操作
一.使用exec運行程序
 exec命令從TCL腳本中進行程序
如: set a [expr 1+1]
 exec命令支持全套的I/O重定向和管道語法.每個進程通常有三個與之關聯的I/O通道:標準輸入,標準輸出以及標準錯誤輸出.通過I/O重定向,可以是這些I/O通道轉向事先有Tcl的open命令打開的文件或I/O通道.管道是這樣一個進程鏈,一個命令的標準輸出掛接到管道中另一個命令的標準輸入.可以將任意數量的程序連接起來形成管道.
 I/O重定向語法的基本思路爲: | 代表管道, > 代碼輸出, < 代表輸入,使用&來將標準錯誤輸出合併到標準輸出中,使用2>來將標準錯誤輸出單獨分離出來.你可以通過使用@來使用自己的I/O通道.
例如: set n  [exce  sort  < /ect/passwd | uniq | wc -1 2>  /dev/null]
 例子說明如下:使用exec來執行管道中的三個程序.第一個程序是sort.它從文件/etc/passwd中接收輸入.sort的輸出通過管道發送給uniq,它消除所有重複的行.uniq的輸出又通過管道發送給wc,由它來計算出相應的行數.將命令的錯誤輸出轉送到空設備以抑制任何錯誤信息.

二.file命令
file名字提供了幾種檢測文件系統中文件狀態的方法.
常用的file方法介紹:
 使用file join來構造文件名
 使用file split對文件名進行分段
 使用file copy對文件進行拷貝
file copy  ?-force?  file1 file2
 使用file mkdir創建目錄
file  mkdir  dir dir....
 使用file delete刪除文件
file detete  ?-force?  name name.....
 使用file rename重新命名文件和目錄
file rename  ?-force?  old  new
 返回文件的最近存取時間
file atime name
 返回name所描述的文件名的目錄部分
file dirname name
 迴文件是否可被執行
file executable name
 返回文件是否存在,返回1表示存在,0表示文件不存在。
file exists name
 返回文件的擴展名
file extension name
 判斷是否爲目錄
file isdirectory name
 判斷是否爲文件
file isfile name
 以數組形式返回。執行lstat系統函數。存儲在varName
file lstat name varName
 文件的最近修改時間
file mtime name
 判斷文件是否屬於你
file owned name
 判斷文件是否可讀。
file readable name
 讀出符號連接的真正的文件名
file readlink name
 返回不包括最後一個點的字符串
file rootname name
 返回文件的大小
file size name
 調用stat內和調用,以數組形式存在varName中
file stat name varName
 返回最後一個斜線以後的部分
file tail name
 返回文件類型file, directory, characterSpecial, blockSpecial, fifo, link, 或socket
file type name
 判斷文件是否可寫
file writable name
三.對I/O命令的總結
打開文件進行I/.O操作
   open命令建立一個指向文件或進程管道的I/O通道,open返回值爲I/O通道標識符.可以將這個結果保存在變量中並像使用stdout,stdin和stderr等標識符那樣來使用這個變量.基本語法爲:
   open what  ?access?  ?permissions?
 what變元要麼是一個文件名,要麼就是一個類似於exec命令所使用的管道描述.
 access變元有兩種形式,即可以是一種於fopen函數庫兼容的短字符序列,也可以是一個包含posix存取標誌的列表.
讀寫操作
 puts命令向輸出通道寫入一個字符串和一個換行符.它接收一個用來阻止通常要追加到輸出通道中的換行符的-nonewline變元
語法爲:puts  ?-nonewline? ?channel? string
 gets命令讀取一行輸入,而且有兩種形式.只帶有一個變元的,gets返回從指定I/O通道中讀取的行.;帶有第2個變元varname,gets就將行內容存儲到命令的變量中並返回讀取的字節數.
語法爲:gets  channel  ?varname?
 read命令成功讀取數據
語法爲:read  channel  ?numBytes?
      read   -nonewline  channel
    read有2種形式,可以指定-nonewline變元或numBytes變元,但不能同時指定2個變元.不帶numBytes,它就會讀取並返回整個文件.給的一個字節記數變元,read就會返回那個數據的信息.
  隨機讀取I/O
seek命令和tell命令提供了對I/O通道的隨機存取
關閉I/O通道
close命令釋放與I/O通道關聯的操作系統資源

exit和pid命令
exit命令用來終止腳本的執行.
pid命令返回當前進程的進程ID.

第九部分:如何利用tcl和jacl編寫測試腳本

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/javazat/archive/2009/02/16/3896232.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章