Tcl parser 處理的特殊字元
相較於其他語言, Tcl 的基本語法規則非常簡單, parser 只認得幾個特殊字元.
- 參數分隔字元: (空格)
- 命令分隔字元: ;
可用以將數個命令放在同一列, 例如: puts hello ; puts world - 註解字元: (放在一個命令最前面的) #
注意: 如何在同一列的左邊寫命令, 右邊寫註解?
set msg "hello, world!" ; # this is a comment -
變數代換字元: $
- 為什麼在 簡介 單元的範例中, set 後面的 msg 不要加 $, 而 puts 和 format 後面的 msg 要加 $ ? 因為 puts 和 format 對變數的名字沒有特別的興趣, 把所有參數當做字串看; 而 set 則把參數當做變數的名字看. 究竟何時要把參數當做一般字串, 何時要把參數當做變數的名字, 由各個命令自行決定. 大部分命令對變數的名字沒有特別的興趣, 他們之所以看起來像是可以處理變數, 完全是因為 parser 事先將 $... 代換過了.
- 刪除變數: unset msg val
(當然, unset 對變數的名字有興趣, 所以不要加 $)
-
陣列變數代換字元: $...(...)
- 例: set days(jan) 31 ; set days(feb) 28 ; set days(mar)
31
之後可以這樣用: format "There are %d days in Februrary" $days(feb) - 陣列的 "註標" 可以是任何字串, 這在其他語言中叫做 associative array, hash, map, 或是 dictionary.
- 注意: $days(jan), $days(Jan), $days( jan) 是 days 陣列中三個不一樣的元素. 同樣地, $dm(1), $dm(01), $dm( 1) 則是 dm 陣列中三個不一樣的元素.
- 所以 Tcl/Tk 中雖然沒有多維陣列, 我們還是可以用
"有規律的註標名稱" 來達到相同的效果: set data(3,7) hello
在這裡 3,7 整個被視為一個字串. - 看看一個陣列內有那些 "註標" 有定義: array names days
注意: array names ... 傳回的註標順序沒有什麼章法. - 刪除陣列當中的一個元素: unset days(mar)
刪除整個陣列: unset days
- 例: set days(jan) 31 ; set days(feb) 28 ; set days(mar)
31
-
命令結果代換 (command substitution): [ ... ]
- 題外話: 用 llength "how many words are there?" 可以計算字串內有幾個 "字" (即字串被空格分割成幾段)
- 假設 days 陣列內 jan, feb, mar 等三個註標對應的元素有定義, 則 程式設計師下 llength [array names days] 時, parser 會先處理 [...], 最後 llength 這個命令接手時, 看到的命令是 llength jan feb mar
-
簡單的 Tcl parser: 內定不代換 ("Quoting is the default!")
- 除了這些 (還有其他較少用的) 具有特殊意義的代換字元之外, 所有東西一律是字串, 像是 + - * / < > ... 等等.
- 那麼數學運算式與邏輯運算式怎麼辦呢? 用 expr 命令. expr 命令把它所有的參數串成一個很長的字串, 然後當成一個數學/邏輯運算式來計算. (所以傳給 expr 的參數有沒有空格無所謂)
-
避免代換 (quoting)
- \ 取消單一字元的特殊意義.
例: puts \$23.5 - "..." 取消空格的意義.
例: puts "hello" 和 puts hello 效果完全一樣;
但 puts "hello world!" 的雙引號則不可省略. -
{ ... } 取消空格的意義, 也取消所有代換.
試試看以下三例:
set x [expr 3 + 5] set x "I have [expr 3 + 5] dollars. You have $x dollars." set x {I have [expr 3 + 5] dollars. You have $x dollars.}
- \ 取消單一字元的特殊意義.
-
用 quoting 把程式 "冷凍" 成資料; 用 eval 命令 "解凍" 以執行程式:
set x [expr 3 + 5] set x {expr 3 + 5} eval $x
C 語言高手: qsort(3) 的 "把函數當做參數傳遞" 介面, 在 tcl 下應該更簡單吧? -
命令的傳回值:
只有少數命令是用來印資料的, 例如 puts; 但是大部分命令都有傳回值, 例如 set, llength, format, ... Tcl interpreter 在處理完一整列的命令後, 會把最後一個命令的傳回值印出來. puts 只印資料, 沒有傳回值; 而 format 只有傳回值, 不印資料. 所以在程式裡面, 要把 format 出來的結果印出來, 必須和 puts 配合使用.set x [puts hello] puts $x format "%x" 255; format "%x" 38; format "%x" 47 puts [format "%d decimal is %x hex" 255 255]
-
特殊字元的其他功能
- 輸入鍵盤無法敲入的字元: \
例如 \a 為 "嗶聲" (0x7), \n 為換列 (0xa), \xhh 為 "ASCII 碼是 0xhh 的字元". - 把變數的值嵌在字串當中: ...${...}...
例如 set middle "ma"; puts infor${middle}tion (這個功能可以用來動態產生變數名稱) - 奇怪的變數名稱 (建議不要這樣做!):
${...}
例如 set 名字 李大明; info vars; puts ${名字}
又如 set "max speed" 120; info vars; puts ${max speed}
- 輸入鍵盤無法敲入的字元: \
- 本頁最新版網址: https://frdm.cyut.edu.tw/~ckhung/b/tcl/parser.php; 您所看到的版本: February 14 2012 02:32:25.
- 作者: 朝陽科技大學 資訊管理系 洪朝貴
- 寶貝你我的地球, 請 減少列印, 多用背面, 丟棄時做垃圾分類。
- 本文件以 Creative Commons Attribution-ShareAlike License 或以 Free Document License 方式公開授權大眾自由複製/修改/散佈。