tcl是每個人都必備的技能,不僅僅指工具自帶的tcl命令,拋開工具本身的tcl用法更應該熟練的使用。既然是必備的技能,每個人都很熟練,我這裡就撿一點重要的講講,供大家參考參考(重要性不分先後)。
info script 經常我們需要source某個文件的同時又想source這個文件所在目錄下的其他文件,通過info script,我們可以得到這個腳本所在的目錄(返回相對路徑),經常和file命令一起用返回絕對路徑。
info exist var 判斷某個變量是否存在,例如
set a "hello"; info exist a; 注意這裡不需要加$符號
rename old_name new_name,可能有些情況下需要改變原來命令的名字,例如:
rename getEcoMode abc; abc
time {commands} 用來衡量某個命令消耗的時間。例如:
time {dbGet top.insts}
雖然命令消耗的時間短,但是如果有很多次循環,所消耗的時間就很可觀了。可以通過這個tcl命令來篩選出實現同一個目的消耗時間最短的命令
exec linux_command 執行linux的命令,例如:
exec touch aa
eval $var 動態構造命令,比如說一個變量中套另一個變量等,例如
set a "hello world"
#set a "noodle"
set b "puts \"want to say $a\""
#set b "puts \"want to eat $a\""
eval $b
通過改變變量a,或者改變變量b,實現了動態的命令。
file [option] $var option有很多,想要知道有哪些option, 有兩種方法,一,man: man file;二,使用錯誤的option,例如 file a
file dirname /a/b/c
file tail /a/b/c
file normalize ./
同perl/C等語言一樣,tcl也有模塊:
package require $package
通過auto_path這個變量來得到模塊所在的路徑,這是個很有用的變量,經常我用這個變量來獲得工具所在的路徑
echo $auto_path
我們在起變量名字的時候,很可能重複。一般通過局部變量或全局變量來區分這些變量,但是有時候這個還不夠,可以採用名字空間來區分不同變量,下面舉個簡單的例子:
namespace eval xx{}
set xx::a "hello"
set ::a "asia"
echo $::a
echo $a
echo $xx::a
namespace delete xx
regexp [option] $pattern $string [new_var]
這裡的option包括:
-nocase : 忽略大小寫
-inline :返回匹配的內容而不是1/0
-all :匹配所有的內容,而不是匹配一次就停止
-linestop: 匹配多行,
inline的用法和[new_var]的用法類似,大家可以仔細體會下下面的例子:
set a "abcdefghijkl"
regexp "(b.*h).*(jk)" $a x y z 可以看看x/y/z的結果:x是所有的內容,y是第一個括號內容,z是第二個括號內容
regexp -inline "(b.*h).*(jk)" $a
all:
set a "a b c b d e b"
regexp -all "b" $a
linestop: 這個一般和-all -inline一起使用
例如下面的例子:
set a "
aisb
b
cisd
"
regexp -all -inline ".*is.* "$a
regexp -all -linestop ".*is.*" $a
regsub和regexp類似,只是不只是查找,還返回替換後的值
經常比較混淆的東西是list和string,同一個東西,既可以當做list,也可以當做string,為了區分,我就簡單的區別一下:
任何字符串都可以當成string
任何有空格的字符串都可以當成list
當做list用和當做string用的命令不同,其中最容易混淆的是append (用於string)和lappend(用於list)命令,可以仔細體會一下下面的例子:
set a "this is hello"
lappend a "world"
append a "world"
注意這裡的a都沒有$符號
concat $lista listb 多個list合併
lindex $list $index 返回第$index個數
llength $list list中元素的個數,以空格區分每個元素
lsort [option] $list
lsort -unique $list 將list中重複元素刪除
其他的list命令就不一一解釋了:
lrange/linsert/lreplace/...
string相關的命令,也不詳細解釋了:
string compare
string tolower
string toupper
string trimleft
catch { command }一個用於debug的命令,經常被我用作其他用途:通常如果一個命令產生error,而我們又想繼續下去,用catch,就可以繼續執行下面的命令
TCL有很多自帶的函數,採用expr命令進行計算
expr abs(-3) 取絕對值
expr int(3.13)取整,返回的是整數
expr ceil(3.13) 返回3.0,和int類似,不同的是返回的是浮點數
expr floor(3.13) 返回4.0,
expr round(3.13) 四捨五入取值
expr rand() 取0-1隨機數
expr fmod(9,2) 取餘數
在計算的時候通常會碰到兩個問題:
整數和浮點數:
expr 122/12 由於分子分母都是整數,所以返回的也是整數
expr 122/(12*1.0) 分母變成了浮點數,返回的也是浮點數
二進位和十進位:
expr int(3.9999999999999) 期待結果是3,但實際上返回4,這就是二進位和十進位在小數轉換過程中的精度損失造成的錯誤
主要用於參數傳遞,C語言中的參數有傳值調用和引用調用,同樣TCL的參數也有這種功能,這就是upvar命令。下面舉兩個例子可以仔細體會一下傳值和引用結果和用法的區別
1. 普通傳值調用
set f 12
proc tmp_incr { var } { incr var}
tmp_incr $f
2. 引用調用
set f 12
proc tmp_incr { var } {upvar $var t ; incr t}
tmp_incr f
將list中的元素付給變量,例如:
set a "aa bb cc"
lassign $a x y z 直接賦值給x,y,z
array [option] array_name
數組有兩種創建方法:
array a {x jim y tom}
或者:
set a(x) jim
set a(y) tom
通常array和普通的變量可能會用一個字符表示,所以用之前需要unset:
unset a
array unset a
option包括:names,get等,同樣可以通過故意敲錯option來獲得提示
array names a 返回key+value
array get a 返回key
數組只有一維的,可以通過特殊分隔符來模擬多維數組:
set a(x,y) valuea
set a(y,z) valueb
set a(x)(y) valuea
set a(y)(z) valueb
用於debug腳本,雖然很有用,但是我沒用過,略
為了顯示漂亮或取指定的位數等可以用format
set long_a 12.345
set short_a [format %1.2f $long_a]
set string_a "abcde"
puts "[format %-20s $string_a]"這裡的-號表示左對齊
if/else/switch/continue/return/文件件讀寫操作略(這個字戳中了多少人的心。哈哈)
新的一年,有什麼新的期待,新的願望,在評論裡面寫寫吧,看看年底有沒有實現。