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


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


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

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

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

1.1 條件表達式

條件表達式

意義

1.文件類檢測,例如[ -e /tmp/a.log ]。如非特別說明,則所有文件類操作都會追蹤到軟鏈接的源文件。

-e file

文件是否存在(exist)

-f file

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM