shell測試命令test、[ ]、[[ ]]

bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.htmlhtml


test可用於測試表達式,支持測試的範圍包括:字符串比較,算術比較,文件存在性、屬性、類型等判斷。例如,判斷文件是否爲空、文件是否存在、是不是目錄、變量是否大於五、字符串是否等於"longshuai"、字符串是否爲空等等。在shell中,幾乎全部的判斷都使用test實現。node

其中[]徹底等價於test,只是寫法不一樣。雙中括號[[]]基本等價於[],它支持更多的條件表達式,還容許在雙中括號內使用邏輯運算符"&&"、"||"、"!"和"()",但這些使用單中括號都能實現,只不過多寫幾個單中括號而已。單中括號[]沒法實現的功能是正則表達式匹配,而[[]]能夠實現。所以,在能使用單中括號的狀況下,無需考慮使用雙中括號。正則表達式

test、[ ]以及[[ ]]都使用條件表達式來完成測試。test和[]用法雖簡單,但語法比較複雜,反而是[[]]的語法較爲簡單。但無論如何,先解釋條件表達式。shell

1.1 條件表達式

條件表達式express

意義安全

1.文件類檢測,例如[ -e /tmp/a.log ]。如非特別說明,則全部文件類操做都會追蹤到軟連接的源文件。bash

-e fileless

文件是否存在(exist)測試

-f filespa

文件是否存在且爲普通文件(file)

-d file

文件是否存在且爲目錄(directory)

-b file

文件是否存在且爲塊設備block device

-c file

文件是否存在且爲字符設備character device

-S file

文件是否存在且爲套接字文件Socket

-p file

文件是否存在且爲命名管道文件FIFO(pipe)

-L file

文件是否存在且是一個連接文件(Link)

2. 文件屬性檢測,如test -r /tmp/a.log。如非特別說明,則全部文件類操做都會追蹤到軟連接的源文件。

-r file

文件是否存在且當前用戶可讀

-w file

文件是否存在且當前用戶可寫

-x file

文件是否存在且當前用戶可執行

-u file

文件是否存在且設置了SUID

-g file

文件是否存在且設置了SGID

-k file

文件是否存在且設置了sbit(sticky bit)

-s file

文件是否存在且大小大於0字節,即用於檢測文件是否爲非空白文件

-N file

文件是否存在,且自上次read後是否被modify

3. 兩個文件之間的比較,如:test file1 -nt file2

file1 -nt file2

(newer than)判斷file1是否比file2新

file1 -ot file2

(older than)判斷file1是否比file2舊

file1 -ef file2

(equal file)判斷file2與file2是否爲同一文件,可用在判斷hard link的斷定上。主要意義在斷定,兩個文件是否均指向同一個分區上的同一個inode

4. 兩個整數之間的斷定,支持正負數,但不支持小數。例如test n1 -eq n2

int1 -eq int2

兩數值相等(equal)

int1 -ne int2

兩數值不等(not equal)

int1 -gt int2

n1大於n2(greater than)

int1 -lt int2

n1小於n2(less than)

int1 -ge int2

n1大於等於n2(greater than or equal)

int1 -le int2

n1小於等於n2(less than or equal)

5. 斷定字符串

-z string

(zero)斷定字符串是否爲空?若string爲空字符串,則爲true

string

-n string

斷定字符串是否非空?若string爲空字符串,則false。注:-n可省略

string1 = string2

string1 == string2

string1和string2是否相同。相同則返回true。"=="和"="等價,但"="可移植性更好

str1 != str2

str1是否不等於str2,若不等,則返回true

str1 > str2

str1字母順序是否大於str2,若大於,則返回true

str1 < str2

str1字母順序是否小於str2,若小於,則返回true

6.邏輯運算符,例如:test -r filename -a -x filename

-a或&&

(and)兩表達式同時爲true時才爲true。"-a"只能在test或[]中使用,&&只能在[[]]中使用

-o或||

(or)兩表達式任何一個true則爲true。"-o"只能在test或[]中使用,||只能在[[]]中使用

!

對錶達式取反

( )

用於改變表達式的優先級,爲了防止被shell解析,應該加上反斜線轉義\( \)

 

1.2 test和[ ]的用法說明

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 ]。

不管參數數量多少個,總的來講仍是對條件表達式的測試,因此最重要的仍是條件表達式的邏輯結果。

1.3 [[ ]]

[[]]基本等價於[],但有些功能寫法更簡潔,且[[]]提供了[]所不具有的正則表達式匹配。因此,[[]]的功能能夠認爲是[]和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.4 使用建議

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.另外,在[]和[[]]中,每一個地方都有空格。這不是書寫建議,而是強制要求的格式。

相關文章
相關標籤/搜索