在 Bash 腳本中我們一般會使用 test 命令來進行條件檢查。test 命令的返回值為 0 或 1。0 表示 true, 1 表示 false。簡單起見,我們可以直接認為 test 的結果為 true 或 false。
還可以使用中括號代替 test,需要注意的是括號和表達式之間一定要留有空格,所以下面的兩種寫法是等同的:
test "$1" = "$name" 或 [ "$1" = "$name" ]
test 命令的主要用途是檢查字符串、比較整數和檢查文件的屬性。本文將通過簡單的示例介紹 test 命令的常見用法。
檢查字符串
判斷字符串是否為空
test 檢查字符串時,非空的字符串返回 true,空字符串或者沒有參數都返回 false。
if test "$abc"; then echo "It's not an empty string." else echo "It's an empty string." fi
運行上面代碼的輸出結果為:
It's an empty string.
這是因為我們沒有定義變量 abc ,所以 "$abc" 被解釋成了空字符串。
其實使用檢查空字符串的運算符 -n 會讓代碼具有更清晰的含義:
if test -n "$abc"; then echo "It's not an empty string." else echo "It's an empty string." fi
-n 的含義為:字符串的長度不為 0 時返回 true。所以這段代碼的輸出結果和上面一樣。
如果我們需要判斷一個空的字符串可以直接使用運算符 -z:
if test -z "$abc"; then echo "It's an empty string." fi
這段代碼輸出的結果仍然是:
It's an empty string.
判斷字符串相等
test 支持兩個運算符來判斷字符串相等:= 和 ==。
abc="hello" if test "hello" == "$abc"; then echo "You got same string." fi
運行上面代碼的輸出結果為:
You got same string.
因為 = 看起來更像是在賦值,所以我更傾向於使用 ==。但是當你的腳本需要跨平台時,最好還是使用 =(test 中的 = 是 POSIX 標准定義的!)。
如果要判斷兩個字符串不相等,可以使用 != 運算符:
abc="helloo" if test "hello" != "$abc"; then echo "Your word is not 'hello'." fi
運行上面代碼的輸出結果為:
Your word is not 'hello'.
為什么用雙引號把變量包起來?
如果你留意前面的代碼會發現我們在引用變量時都用雙引號包起來了,這是寫 shell 腳本中的一個小技巧。嘗試運行下面的代碼:
abc="hello xx" if test "hello" != $abc; then echo "Your word is not 'hello'." fi
會提示語法錯誤:
因為變量 abc 的值為 "hello xx",在字符串中間有個空格。所以在 Bash 進行命令解釋的時候,上面的 test 命令變成了:
test "hello" != hello xx
這不是一個合法的 test 命令,所以腳本執行時就報錯了!
其實不光是空格,包含在 $IFS 中的其它字符,還有變量為空時,都會造成語法錯誤。所以使用雙引號包裹變量是一種保護機制,可以提高腳本的健壯性。
比較數字(整數)
test 支持整數間的比較操作,可用的運算符有 '-eq','-ne','-lt','-le','-gt','-ge'。
比如判斷兩個整數相等可以使用 -eq 運算符:
num=3 if test "$num" -eq 3; then echo "num is 3." fi
運行上面代碼的輸出結果為:
num is 3.
常見數字運算符的含義分別為:
n1 -eq n2 : 整數 n1 等於 n2 n1 -ne n2 : 整數 n1 不等於 n2 n1 -lt n2 : n1 小於 n2 n1 -gt n2 : n1 大於 n2 n1 -le n2 : n1 小於或等於 n2 n1 -ge n2 : n1 大於或等於 n2
檢查文件屬性
檢查文件的屬性也是 test 常見用法。比如要檢查一個文件的類型是不是普通文件,可以使用 -f 選項:
touch test.sh filename="test.sh" if test -f "$filename"; then echo "It's a regular file." fi
運行上面代碼的輸出結果為:
It's a regular file.
另一個重要的選項是 -d,它用來檢查一個路徑是不是目錄:
dirname="/bin" if test -d "$dirname"; then echo "It's a directory." fi
運行上面代碼的輸出結果為:
It's a directory.
如果是僅僅判斷一個路徑是否存在,可以使用 -e 運算符。它僅檢查文件是否存在而不關心文件的具體類型。
下面是其它一些常用的文件檢查運算符:
-b file : 文件存在並且是塊設備文件。 -c file : 文件存在並且是字符設備文件。 -d file : 文件存在並且是一個目錄。 -e file : 文件存在。 -f file : 文件存在並且是一般文件。 -g file : 文件存在並且設置了 setgid 位。 -h file : 文件存在並且是一個鏈接文件。 -p file : 文件存在並且是一個命名管道(FIFO)。 -r file : 文件存在並且是可讀的。 -s file : 文件存在並且有內容。 -u file : 文件存在並且設置了 setuid。 -w file : 文件存在並且是可寫的。 -x file : 文件存在並且是可執行的。 -S file : 文件存在並且是一個 socket。
總結
個人感覺 test 是 Bash 中很重要的命令。在你掌握了基本的腳本編寫技能后,通過 test 命令並結合 if 等流程語句你可以控制程序的執行流程,從而開啟腳本編程的大門。