TCL語言:trace命令-跟蹤、監(jiān)視
trace命令跟蹤監(jiān)視命令或變量,當(dāng)進行某些操作或出現(xiàn)某些情況時,執(zhí)行指定的跟蹤命令。比如監(jiān)視變量,在變量值發(fā)生改變時就調(diào)用某個命令。
trace命令在《TCL/TK入門經(jīng)典》中有比較詳細的介紹,這本書也是TCL語言最佳入門書籍,建議對照書籍進行學(xué)習(xí)。
設(shè)置(或稱創(chuàng)建)跟蹤監(jiān)視是通過 trace add 子命令進行,格式為
"trace ?add ?類型 ?名稱 ?參數(shù) ?指定命令或代碼段"
類型:包括命令、執(zhí)行情況、變量三種
名稱:要跟蹤監(jiān)視的命令或變量的名字
參數(shù):一般指具體監(jiān)視的內(nèi)容,比如讀取、修改、刪除等等
指定命令或代碼段:在發(fā)生情況時要調(diào)用的命令或代碼段,trace命令在調(diào)用命令時會自動給命令傳遞多個參數(shù),其中第一個參數(shù)固定是當(dāng)前被監(jiān)視的內(nèi)容(大部分情況下是名字,也有當(dāng)前跟蹤的代碼語句)后續(xù)參數(shù)不一定。也就是說,指定了命令后,在調(diào)用時實際執(zhí)行的是 "命令 ?監(jiān)視名字或語句 ?其它參數(shù)1 ?其它參數(shù)2……" 這種。所以在創(chuàng)建自定義命令時,需要用 proc 命令 {args} {……} 這種形式,或者 proc 命令 {name args} {……} 這種形式,當(dāng)然如果參數(shù)總數(shù)固定的話,也可以是 proc 命令 {a b c} {……} 這種(比如變量跟蹤)。
跟蹤監(jiān)視時,trace在調(diào)用指定命令時會附加三個參數(shù):
1.監(jiān)視對象的名稱 2.被修改的新名稱(rename時)或空字符 3.監(jiān)控類型
trace add command 命令名 參數(shù)(rename/delete) 指定命令 rename 監(jiān)視命令被改名 delete 監(jiān)視命令被刪除
執(zhí)行情況跟蹤
trace add execution 命令名 參數(shù) 指定命令 enter —— 調(diào)用命令時執(zhí)行指定的命令 leave —— 命令運行完畢后執(zhí)行指定的命令 enterstep —— 監(jiān)視命令,在命令的每行語句運行前調(diào)用指定的命令 leavestep —— 監(jiān)視命令,在命令的每行語句運行后調(diào)用指定的命令
enter 和 enterstep 模式時,調(diào)用指定命令時附加兩個參數(shù):1.監(jiān)視的命令(帶參數(shù))2.當(dāng)前模式(enter、enterstep)
leave 和 leavestep 時,附加四個參數(shù): 1.監(jiān)視的命令(帶參數(shù)) 2.命令執(zhí)行狀態(tài)代碼(0-成功運行、1-出現(xiàn)錯誤) 3.被監(jiān)視命令或語句的執(zhí)行結(jié)果(無返回值的語句為空字符串) 4.當(dāng)前模式(leave、leavestep)

變量跟蹤
變量跟蹤監(jiān)視時,trace在調(diào)用指定命令時會附加三個參數(shù):
1.變量名
2.元素名(僅限單個數(shù)組元素)或空字符
3.監(jiān)控類型(read、write、unset)
trace add variable 變量名 參數(shù) 指定命令
參數(shù): array —— 監(jiān)視整個數(shù)組,對任意數(shù)組元素進行操作時,執(zhí)行指定的命令
read —— 讀取變量時執(zhí)行指定的命令
write —— 修改變量時執(zhí)行指定的命令
unset —— 刪除變量時執(zhí)行指定的命令

官網(wǎng)論壇中給出的一個"精妙"的例子,實現(xiàn)了只讀變量的功能:

首先,我比較反感這種精妙的代碼,雖然代碼少,但是閱讀性太差(智商高也請照顧照顧大眾)。解釋一下這個例子,首先,trace指定的跟蹤調(diào)用命令,除了自定義命令外也可以是代碼段,就像上面這樣。這段代碼的意思是:當(dāng)觸發(fā)調(diào)用時,先執(zhí)行 "set ::嗶哩 $嗶哩" 這個語句,而根據(jù)TCL的語法,先進行變量替換,所以語句實際是:
set ::嗶哩 "someValue"
即,每當(dāng)對嗶哩進行修改,就會把"someValue"重新賦值給嗶哩(::是全局命名空間),變相實現(xiàn)了常量
隨后執(zhí)行 error read-only 觸發(fā)錯誤,最后的 # 很有意思,前面介紹過,trace在調(diào)用指定命令時會附加參數(shù),如果給出的不是命令名,而是代碼段的話,就會把參數(shù)附加在代碼段后面,這樣會導(dǎo)致代碼段運行報錯。此時在代碼段末尾加一個 # 就可以讓后續(xù)的附加參數(shù)都變成注釋了,就不會導(dǎo)致錯誤了。
對變量的跟蹤監(jiān)視也可以用于數(shù)組元素,對單個數(shù)組元素進行監(jiān)視時與變量相同。對整個數(shù)組進行監(jiān)視可以使用array參數(shù)。

移除跟蹤設(shè)置
trace remove 類型 名稱 參數(shù) 跟蹤命令 trace remove command 名稱 參數(shù) 跟蹤命令 trace remove execution 名稱 參數(shù) 跟蹤命令 trace remove variable 名稱 參數(shù) 跟蹤命令
查看當(dāng)前跟蹤設(shè)置
查看當(dāng)前已有的跟蹤設(shè)置:
trace info 類型 名稱
trace info command 名稱 trace info execution 名稱 trace info variable 名稱
以上分別對應(yīng)命令、運行情況、變量。如果沒有設(shè)置任何跟蹤語句,則返回空字符
簡寫模式
對于常用的語句,trace提供了一些簡寫模式,可以少打幾個單詞
trace variable 名稱 指定參數(shù) 跟蹤指令
相當(dāng)于:trace add variable ?名稱 指定參數(shù) 跟蹤指令
trace vdelete 名稱 指定參數(shù) 跟蹤指令
相當(dāng)于:trace remove variable ?名稱 指定參數(shù) 跟蹤指令
trace vinfo 名稱
相當(dāng)于:trace info variable 名稱