shell指令碼專家指南筆記#4_比較和測試
##
# 本文為《shell指令碼專家指南》一書的學習筆記。
##
4. 比較和測試
通用形式
if [ "$string" = "some_string" ]; then ...
if [ $integer -eq 15 ]; then ...
注意雙引號 "" 的使用,原文說明比較模糊,後來我做了測試。
在test 和 [] 中,如果$a中a未定義,不加雙引號,會導致報錯
"unary operator expected",在[[]]中,沒有此限制。
同樣的,如果$a中a存在空格, 那麼在test和[]中,不加""會導致報錯
"too many arguments",在[[]]中,沒有此限制。
個人建議,對於字串變數名和顯式字串,均採用""進行引用,數字
不用""進行引用。因此,個人認為,通用形式可以表示為
if [ "$string" = "some_string" ]; then ...
if [ "$integer" -eq 15 ]; then ...
關於字串比較運算子 = != > < 和數字比較運算子 -eq -ne -gt -lt 互相對應。
其中-eq等只能運算元字,=等可以運算元字和字串。
另外注意,在test和[]中,字串比較不能使用>和<,因為兩者均返回true,
而在[[]]中,>和<可以正常使用。
[] 和 test 可以互相替換使用,比如
if [ "$a" = "a" ]; then ...
if test "$a" = "a"; then ...
if/then 的一種替換形式。
if [ "$a" = "a" ]; then echo ok; fi
可替換為
test "$a" = "a" && echo ok # [ "$a" = "a" ] && echo ok
多行語句替換
if [ "$a" = "a" ]; then echo ok; echo good;fi
可替換為
test "$a" = "a" && {
echo ok
echo good
}
# [ "$a" = "a" ] && {
# echo ok
# echo good
# }
替換原理,&&連線的語句,只有當前部分為真時,後部分才會執行。
同理,||連線的語句,只有當前部分為假時,後部分才會執行。
多級判斷
# 當txt變數不為空,且txt與txt2不同時,為var賦值"$txt $txt2"
[ "$txt" ] && [ "$txt" != "$txt2" ] && var="$txt $txt2"
# 當txt不等於txt2且num等於num2,或者num2等於100時,執行...
if [ "$txt" != "$txt2" -a $num -eq $num2 ] || [ $num2 -eq 100 ]; then ...
如變數已定義,則...
# 此處$string必加引號,如不加引號,則-n判斷始終為真。
# 不加引號時,對於空變數,會變為[ -n ] ,將-n直接看做了字串,而非運算子。
# 不加引號的情況下,如果string變數有空格,也會報錯。
if [ -n "$string" ]; then ...
if [ "$string" ]; then ...
如變數未定義,則...
# 同理,此處$string也比加引號,否則如果string變數有空格,也會報錯。
if [ -z "$string" ]; then ...
if [ ! "$string" ]; then ...
示例,判斷/etc/hosts是否有nodename字樣。
if [ "`grep nodename /etc/hosts`" ]; then ...
if命令不僅可以判斷變數和數值,還可以判斷命令的返回值。
# 判斷ping nodename -c 3的返回值。
if ping nodemana -c 3 > /dev/null 2>&1; then ...
test -l的特殊例子
# 判斷"hello"字串長度是否大於4。
# 下面的語句會報錯。
test -l "hello" -gt 4 && echo ok
# 下面的句子正常。
/usr/bin/test -l "hello" -gt 4 && ok
原文給出的說法,bash和ksh中有內部的test指令,且不支援-l引數。
只有指定了test的全路徑,才會用系統的test命令,可以支援-l引數。
# 說的雲裡霧繞的,which test,顯示的也是系統的test路徑。
# 具體原因不清楚,這點記住就好。