bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.htmlhtml
test可用於測試表達式,支持測試的範圍包括:字符串比較,算術比較,文件存在性、屬性、類型等判斷。例如,判斷文件是否爲空、文件是否存在、是不是目錄、變量是否大於五、字符串是否等於"longshuai"、字符串是否爲空等等。在shell中,幾乎全部的判斷都使用test實現。node
其中[]徹底等價於test,只是寫法不一樣。雙中括號[[]]基本等價於[],它支持更多的條件表達式,還容許在雙中括號內使用邏輯運算符"&&"、"||"、"!"和"()",但這些使用單中括號都能實現,只不過多寫幾個單中括號而已。單中括號[]沒法實現的功能是正則表達式匹配,而[[]]能夠實現。所以,在能使用單中括號的狀況下,無需考慮使用雙中括號。正則表達式
test、[ ]以及[[ ]]都使用條件表達式來完成測試。test和[]用法雖簡單,但語法比較複雜,反而是[[]]的語法較爲簡單。但無論如何,先解釋條件表達式。shell
|
test和[]的用法很是簡單,但語法較複雜。它們是根據參數的個數來完成測試的,因此測試的結果也依賴於參數的個數。以下所述:
(1).不帶任何參數時,直接返回false。
[root@xuexi ~]# [ ];echo $? 1
(2).只有一個參數時,測試表達式採起的是[ arg ],根據條件表達式的說明,僅當arg爲非空時返回true。
[root@xuexi ~]# test haha;echo $? 0
[root@xuexi ~]# test $abcd;echo $? 1
[root@xuexi ~]# test '';echo $? 1
(3).兩個參數時,有幾種狀況:
①.第一個參數是單目條件運算符,包括文件類測試(如[ -e file1 ])和[ -n string ]、[ -z string ]。
②.第一個參數是"!"時,則只能是[ ! string ],等價於[ ! -n string ]。由於"!"是對條件表達式取反,因此當string爲空時才true。
③第一個參數不是任何有效的操做符。將直接報錯
(4).三個參數時,也有幾種狀況:
①.使用了雙目運算符,如[ file1 -nt file2 ],[ init1 -eq int2 ]以及[ string1 != string2 ]。
②.使用了邏輯運算符,如[ string1 -a string2 ]、[ ! -e file ]、[ ! -z string ]、[ ! -n string ]。
③.使用了括號,則只能是[ (string) ]。
(5).四個參數以上時,則處理方法參照上面。如[ ! string1 == string2 ]、[ string1 == string2 -o string1 == string3 ]。
不管參數數量多少個,總的來講仍是對條件表達式的測試,因此最重要的仍是條件表達式的邏輯結果。
[[]]基本等價於[],但有些功能寫法更簡潔,且[[]]提供了[]所不具有的正則表達式匹配。因此,[[]]的功能能夠認爲是[]和expr命令的相加。
語法格式:
[[ conditional_expression ]]
除了如下特別註明的幾項,其他用法等同[]。
(1).當條件表達式中使用的運算符是"=="或"!="時,該運算符的右邊會被看成pattern被匹配,"=="表示能匹配成功則返回0,"!="則相反。但此時只是通配符匹配,不支持正則表達式匹配。通配符包括:"*"、"?"和"[...]"。
例如:
[root@xuexi ~]# [[ abc == a* ]];echo $? 0 [root@xuexi ~]# [[ abc == a*d ]];echo $? 1
(2).當條件表達式中使用的運算符是"=~"時,該運算符的右邊會被看成正則表達式的pattern被匹配。
例如:
[root@xuexi ~]# [[ abc =~ aa* ]];echo $? 0 [root@xuexi ~]# [[ abc =~ aa.* ]];echo $? 1
(3).除了可使用邏輯運算符!和(),還可使用&&、||,分別表示邏輯與和邏輯或,等價於[]的"-a"和"-o"。可是[[]]再也不支持"-a"和"-o"。
例如:
[root@xuexi ~]# [[ 3 -eq 3 && 5 -eq 5 ]];echo $? 0
總之,除了模式匹配和正則表達式匹配時須要使用[[]],其他時候建議使用[ ]。
1.不管是[]仍是[[]],都建議對其內變量、字符串使用雙引號包圍。換句話說,能作字符串比較的時候,不要用數值比較。
例如:
name="Ma long" [ $name = "Ma long" ]
上面的測試語句將報錯,由於在變量替換階段,$name被替換爲Ma long,但它們沒有在引號內,因而進行單詞拆分,這就等價於執行的是[ Ma long = "Ma long" ],顯然這是錯誤的語法。因此,建議加上雙引號:
[ "$name" = "Ma long" ]
2.數值比較時,建議雙方同時加0,避免變量爲空時報錯。
例如,變量a爲空,下面的表達式是錯誤的。由於它被shell解析後至關於[ -eq 7 ],而這是錯誤的語法。
[root@xuexi ~]# [ $a -eq 7 ] -bash: [: -eq: unary operator expected
採起第一種建議,將$a使用引號包圍的話,仍是錯的。由於被shell解析後至關於[ "" -eq 7 ],字符串和數值沒法比較。注意這裏的報錯和上面的錯誤信息不同。
[root@xuexi ~]# [ "$a" -eq 7 ] -bash: [: : integer expression expected
因此最好的方法是將它改成字符串來測試。或者雙方同時加0,因爲此處有一方是常量數值,因此只需爲變量部分加0便可。
[root@xuexi ~]# [ "$a" = "7" ]
[root@xuexi ~]# [ $((a+0)) -le 8 ]
3.當變量可能爲空的時候,強烈建議在變量的基礎上加上其餘輔助字符串。看過/etc/init.d下的腳本的人確定都見過這種用法。
上面的語句雖然能正確測試。其實更安全的方法是採用下面的形式:
[root@xuexi ~]# [ "a$a" = "a7" ] # 判斷a是否爲7 [root@xuexi ~]# [ "a$a" = "a" ] # 判斷a是否爲空 [root@xuexi ~]# [ ! -z "$a" -a "a$a" = "a7" ] # a不爲空且a=7時才爲真
4.另外,在[]和[[]]中,每一個地方都有空格。這不是書寫建議,而是強制要求的格式。