1. 程式人生 > 實用技巧 >六、Shell指令碼的條件測試

六、Shell指令碼的條件測試

一、條件測試語法

語法1:test <測試表達式>
利用test命令進行條件測試表達式的方法。test命令與<測試表達式>之間至少有一個空格。

語法2:[ <測試表達式> ]
通過[](單中括號)進行條件測試表達式的方法,和test命令用法相同。[]的邊界和內容之間至少有一個空格。

語法3:[[ <測試表達式> ]]
通過[[]](雙中括號)進行條件測試表達式的方法,比test和[]更新的語法格式。[[]]的邊界和內容之間至少有一個空格。

語法4:((<測試表達式>))
通過(())(雙小括號)進行條件測試表達式的方法,一般用於if語句。(())(雙小括號)兩端不需要有空格。
注意:
1)、語法1中的test命令和語法2中的[]是等價的。語法3中的[[]]為擴充套件的test命令,語法4中的(())常用於計算,:建議使用相對友好的語法2,即中括號([])的語法格式。
2)、在[[]](雙中括號)中可以使用萬用字元等進行模式匹配,這是其區別於其他幾種語法格式的地方。
3)、&&、||、>、<等操作符可以應用於[[]]中,但不能應用於[]中,在[]中一般用-a、-o、-gt(用於整數)、-lt(用於整數)代替上述操作符。
4)、對於整數的關係運算,也可以使用Shell的算術運算子(())

1、test條件測試的簡單語法及示例

test條件測試的語法格式為:test<測試表達式> 對於如下語句: test -f file && echo true || echo false

該語句表示如果file檔案存在,則輸出true,否則(||)輸出false。這裡的&&是並且的意思。test的-f引數用於測試檔案是否為普通檔案,test命令若執行成功(為真),則執行&&後面的命令,而||後面的命令是test命令執行失敗之後(為假)所執行的命令。 test命令測試表達式的邏輯也可以用上述表達形式的一半邏輯(即僅有一個&&或||)來測試,示例如下。

test -f /tmp/test.txt && echo 1 #<==若表示式成功,則輸出1。 test -f /tmp/test.txt || echo 0 #<==若表示式不成功,則輸出0。

提示:關於test測試表達式的更多知識可執行man test檢視幫助,大部分場景都會使用[]的語法替代test命令的語法。

案例

在test命令中使用-f選項(檔案存在且為普通檔案則表示式成立)測試檔案。

判斷/tmp是否存在一個ywx的檔案,存在則列印true,不存在則列印false
[root@node1 ~]# test -f /tmp/ywx && echo true || echo false
false   #ywx檔案不存在,列印false
[root@node1 ~]# touch /tmp/ywx
[root@node1 ~]# test -f /tmp/ywx && echo true || echo false
true    #ywx檔案存在,列印true

在test命令中使用-z選項(如果測試字串的長度為0,則表示式成立)測試字串。

判斷king的字元長度是否為0,為0則列印1,不為0則列印0
[root@node1 ~]# test -z "king" && echo 1 || echo 0
0
#king的字串長度不為0,列印結果為0

判斷是否給一個變數SEAL賦值,賦值則列印結果為0,沒有賦值則列印結果為1
[root@node1 ~]# echo $SEAL

[root@node1 ~]# test -z "$SEAL" && echo 1|| echo 0
1
#SEAL變數沒有被賦值,結果顯示為1
[root@node1 ~]# SEAL=ywx
[root@node1 ~]# echo $SEAL
ywx
[root@node1 ~]# test -z "$SEAL" && echo 1|| echo 0
0
#SEAL的賦值為ywx,列印結果為0

2、[](中括號)條件測試語法及示例

[]條件測試的語法格式為:[ <測試表達式> ],注意[]兩邊有空格

-f /tmp/ywx.txt ] && echo 1 || echo 0

如果/tmp/ywx.txt檔案存在,則輸出1,否則(||)輸出0。這裡的&&表示並且。[]的應用同test命令,若中括號裡的命令執行成功(返回真),則執行&&後面的命令,否則執行||後面的命令。 []測試表達式的邏輯也可以用如下的語法來判斷邏輯的表示式寫法(test命令的用法也適合於此),即: [ -f /tmp/ywx.txt ] && echo 1 #<==若表示式成功,則輸出1。 [ -f /tmp/ywx.txt ] || echo 0 #<==若表示式不成功,則輸出0

提示:[]命令的選項和test命令的選項是通用的,因此,使用[]時的引數選項可以通過man test命令獲得幫助。

案例

在[]使用-f選項(檔案存在且為普通檔案則表示式成立)測試檔案。

判斷/tmp是否存在一個ywx的檔案,存在則列印true,不存在則列印false
[root@node1 ~]# [ -f /tmp/ywx ]&& echo true|| echo false
false
[root@node1 ~]# touch /tmp/ywx
[root@node1 ~]# [ -f /tmp/ywx ]&& echo true|| echo false
true

3、[[]]條件測試語法及示例

[[]]條件測試的語法格式為:[[ <測試表達式> ]]。注意[[]]兩邊有空格

[[ -f /tmp/ywx.txt ]] && echo 1 || echo 0

如果/tmp/ywx.txt檔案存在就輸出1,否則(||)就輸出0。這裡的&&表示並且。[[]]的應用屬於[]和test命令的擴充套件命令,功能更豐富也更復雜。如果雙中括號裡的表示式成立(為真),則執行&&後面的命令,否則執行||後面的命令。 [[]]測試表達式的邏輯也可以使用如下的部分邏輯形式,即: [[ -f /tmp/ywx.txt ]] && echo 1 #<==若表示式成功則輸出1。 [[ -f /tmp/ywx.txt ]] || echo 0 #<==若表示式不成功則輸出0。

另外,邏輯操作符&&和||的兩端可以有空格也可以無空格。

雙中括號內部的兩端要有空格,[[]]裡的測試判斷選項,也可以通過man test來獲得,[[]]表示式與[]和test用法的選項部分是相同的,其與[]和test測試表達式的區別在於,在[[]]中可以使用萬用字元等進行模式匹配;並且&&、||、>、<等操作符可以應用於[[]]中,但不能應用於[]中,在[]中一般使用-a、-o、-gt(用於整數)、-lt(用於整數)等操作符代替上文提到的用於[[]]中的符號。除了使用萬用字元功能之外,建議放棄這個雙中括號的寫法,雖然它是較新的test命令的語法格式。

案例

在[[]]使用-f選項(檔案存在且為普通檔案則表示式成立)測試檔案。

判斷/tmp是否存在一個ywx的檔案,存在則列印true,不存在則列印false
[root@node1 ~]# [[ -f /tmp/ywx ]]&& echo true|| echo false
false
[root@node1 ~]# touch /tmp/ywx
[root@node1 ~]# [[ -f /tmp/ywx ]]&& echo true|| echo false
true

二、檔案測試表達式

-d(directory)目錄
檔案存在且為目錄則位真,及測試表達式成立

-f(file)檔案
檔案存在且為普通檔案則位真,及測試表達式成立

-e(exist)
檔案存在則為真,及測試表達式成立。不區分檔案或目錄。

-r(read)檔案
檔案存在且有可讀許可權則為真,及測試表達式成立

-s(size)檔案
檔案存在且檔案小大不為0則為真,及測試表達式成立

-w(write)檔案
檔案存在且有可寫許可權則為真,及測試表達式成立

-x(executable)檔案
檔案存在且有可執行許可權則為真,及測試表達式成立

-L(link)檔案
檔案存在且為連結檔案則為真,及測試表達式成立

f1 -nt f2, nt(newer than)
檔案f1比檔案f2新則為真,及測試表達式成立。根據檔案的修改時間來計算

f1 -ot f2, ot(older than)
檔案f1比檔案f2舊則為真,及測試表達式成立。根據檔案的修改時間來計算

1、普通檔案測試表達式示例

[root@node1 ~]# [ -f /etc/hosts ]&&echo 1|| echo 0
1
#檔案存在則為1,不存在則為0

2、目錄檔案(測試檔案型別)

[root@node1 ~]# [ -f /etc ]&&echo 1|| echo 0
0   #不存在/etc的普通檔案
[root@node1 ~]# [ -d /etc ]&&echo 1|| echo 0
1   #/etc存在且為目錄
[root@node1 ~]# [ -e /etc ]&&echo 1|| echo 0
1  #/etc存在就行,不管是目錄還是檔案
#/etc目錄存在為1,不存在為0

3、測試檔案屬性示例

[root@node1 ~]# ll /etc/hosts
-rw-r--r--. 1 root root 158 Jun  7  2013 /etc/hosts
[root@node1 ~]# [ -r /etc/hosts ]&& echo 1|| echo 0
1   #有r許可權
[root@node1 ~]# [ -w /etc/hosts ]&& echo 1|| echo 0
1   #有w許可權
[root@node1 ~]# [ -x /etc/hosts ]&& echo 1|| echo 0
0   #無x許可權

[root@node1 ~]# su - ywx
Last login: Sun Oct  4 03:32:51 CST 2020 on pts/0
ni hao shell
[ywx@node1 ~]$ ll /etc/hosts
-rw-r--r--. 1 root root 158 Jun  7  2013 /etc/hosts
[ywx@node1 ~]$ [ -r /etc/hosts ]&&echo 1||echo 0
1
[ywx@node1 ~]$ [ -w /etc/hosts ]&&echo 1||echo 0
0
[ywx@node1 ~]$ [ -x /etc/hosts ]&&echo 1||echo 0
0

測試檔案的讀、寫、執行等屬性,不光是根據檔案屬性rwx的標識來判斷,還要看當前執行測試的使用者是否真的可以按照對應的許可權操作該檔案。

4、測試檔案大小是否為0

[root@node1 ~]# ll /etc/hosts
-rw-r--r--. 1 root root 158 Jun  7  2013 /etc/hosts
[root@node1 ~]# ll /tmp/ywx
-rw-r--r-- 1 root root 0 Oct  5 22:46 /tmp/ywx

[root@node1 ~]# [ -s /etc/hosts ]&&echo 1||echo 0
1
[root@node1 ~]# [ -s /etc/ywx ]&&echo 1||echo 0
0

5、測試shell變數

[root@node1 ~]# file1="/etc"
[root@node1 ~]# echo $file1
/etc
[root@node1 ~]# [ -f "$file1" ]&&echo 1||echo 0
0   #變數$file1不為檔案
[root@node1 ~]# [ -d "$file1" ]&&echo 1||echo 0
1   #變數$file1是目錄
[root@node1 ~]# [ -s "$file1" ]&&echo 1||echo 0
1    #變數$file1大小不0
[root@node1 ~]# [ -e "$file1" ]&&echo 1||echo 0
1    #變數$file1存在

注意:用[]測試變數時,如果被測試的變數不加雙引號,那麼測試結果可能會是不正確的

[root@node1 ~]# unset KAKA
[root@node1 ~]# echo $KAKA   #變數KAKA沒有賦值

[root@node1 ~]# [ -f $KAKA ]&& echo 1||echo 0
1
[root@node1 ~]# [ -f "$KAKA" ]&& echo 1||echo 0
0
#對變數而言不加"",當該變數沒有賦值時結果不正確的

6、特殊條件測試表達式案例

以下寫法適用於所有的條件測試表達式,是工作中比較常用的替代if語句的方法。判斷條件測試表達式的條件成立或不成立後,還需要繼續執行多條命令語句的語法形式如下:

[ 條件1 ] &&{ 命令1 命令2 命令3 }

上面的判斷相當於下面if語句的效果。

if [ 條件1 ] then

命令1

命令2

命令3

fi

如果/etc存在且為目錄時則同時列印etc is exist和 etc is directory
[root@node1 ~]# [ -d /etc ] && { echo "etc is exist";echo "etc is directory"; }||echo "etc not exist"
etc is exist
etc is directory
#注意{}兩邊要有空格,每條命令以";"結尾

三、字串測試表達式

1、操作符

字串測試操作符的作用包括:比較兩個字串是否相同、測試字串的長度是否為零、字串是否為NULL等

-n "字串"
若字串長度不為0,則為真,及測試表達式成立,n(no zero)

-z "字串"
若字串長度為0,則為真,及測試表達式成立,z(zero)

"字串1" = "字串2"
若字串1等於字串2,則為真,及測試表達式成立,也可以使用"=="

"字串1" != "字串2"
若字串1不等於字串2,則為真,及測試表達式成立,不能使用!==

·對於字串的測試,一定要將字串加雙引號之後再進行比較。如[ -n "$myvar" ],特別是使用[]的場景。
·比較符號(例如=和!=)的兩端一定要有空格。
·“!=”和“=”可用於比較兩個字串是否相同。

2、案例

[root@node1 ~]# [ -n "abc" ] && echo 1 || echo 0  #<==如果字串長度不為0,則輸出1,否則輸出0。
1 #<==因為字串為abc,長度不為0,因此為真,輸出1。
[root@node1 ~]# test -n "abc" && echo 1 || echo 0 #<==test的用法同上述[]的用法。1
[root@node1 ~]# test -n "" && echo 1 || echo 0
0
[root@node1 ~]# var="ywx1" #<==給變數var賦值ywx1字串。
[root@node1 ~]# [ -n "$var" ] && echo 1 || echo 0   #<==如果字串長度不為0,
                                                           則輸出1,否則輸出0。
1 #<==因為變數var內容字串為ywx1,長度不為0,因此為真,輸出1。
[root@node1 ~]# [ -n $var ] && echo 1 || echo 0 #<==去掉雙引號在這裡看起來也是對的,不過還是加上為好。
1
[root@node1 ~]# var="ywx1"
[root@node1 ~]# [ -z "$var" ] && echo 1 || echo 0  #<==使用-z,變數長度為0,則為真。
0   #<==變數var的值為ywx1,長度不為0,所以表示式不成立,輸出0。
[root@node1 ~]# [ "abc" = "abc" ] && echo 1 || echo 0
#<==字串相等,輸出1,注意“=”兩端要有空格。
1
[root@node1 ~]# [ "abc" = "abd" ] && echo 1 || echo 0#<==字串不相等,輸出0,注意“=”兩端要有空格。
0
[root@node1 ~]# [ "$var" = "ywx1" ] && echo 1 || echo 0
#<==變數值和字串相等,輸出1。
1
[root@node1 ~]# [ "$var" == "ywx1" ] && echo 1 || echo 0
#<==使用“==”代替“=”,注意“=”兩端要有空格。
1
[root@node1 ~]# [  "$var"!= "ywx1" ] && echo 1 || echo 0
0

進行字串比較時,等號兩端沒有空格帶來的問題

[root@node1 ~]# ["abc"="1"] && echo 1||echo 0  #<==若等號兩端不帶空格,則會出現明顯的邏輯錯誤。
1  #<==明明表示式不成立,卻輸出了1。
[root@node1 ~]# [ "abc" = "1" ] && echo 1||echo 0 #<==帶空格的就是準確的。
0  #<==表示式不成立,輸出0
#字串比較時若等號兩端沒有空格,則會導致判斷出現邏輯錯誤,即使語法沒問題,但是結果依然可能不對。

字串不加引號可能帶來的問題。

[root@node1 ~]# var="" #<==將變數內容置為空。
[root@node1 ~]# [ -n "$var" ] && echo 1 || echo 0  #<==有雙引號。
0 #<==給變數加雙引號,返回0,-n不為空時為真,因為變數內容為空,因此輸出0是對的。
[root@node1 ~]# [ -n $var ] && echo 1 || echo 0     #<==去掉雙引號。
1 #<==同樣的表示式,不加引號和加雙引號後測試的結果相反,可見加雙引號的重要性。
[root@node1 ~]# [ -z "$var" ] && echo 1 || echo 0 #<==如果字串長度為0,則輸出1,否則輸出0。
1
#字串不加雙引號,可能會導致判斷上出現邏輯錯誤,即使語法沒問題,但是結果依然可能不對。

四、整數二元比較操作符

1、整數二元比較操作符

在[]和test中使用的比較符

-eq:相等
-ne: 不等於
-gt: 大於
-ge: 大於等於
-lt: 小於
-le:小於等於

在(())和[[]]中使用的比較符號

==或==
>
>=
<
<=
1)·“=”和“!=”也可在[]中做比較使用,但在[]中使用包含“>”和“<”的符號時,需要用反斜線轉義,有時不轉義雖然語法不會報錯,但是結果可能會不對。
2)·也可以在[[]]中使用包含“-gt”和“-lt”的符號,但是不建議這樣使用。
3)·比較符號兩端也要有空格。

2、案例

二元數字在[]中使用“<”、“>”非標準符號的比較。

[root@node1 ~]# [ 2 > 1 ] && echo 1 || echo 0
1
[root@node1 ~]# [ 2 < 1 ] && echo 1 || echo 0
1  #<==這裡的結果邏輯不對,條件不成立,則應該返回0,可見,“<”操作符在[]裡使用時會帶來問題。
[root@node1 ~]# [ 2 \< 1 ] && echo 1 || echo 0
0 #<==轉義後這裡是正確的。
[root@node1 ~]# [ 2 = 1 ] && echo 1 || echo 0   #<==比較相等符號是正確的。
0
[root@node1 ~]# [ 2 = 2 ] && echo 1 || echo 0   #<==比較相等符號是正確的。
1
[root@node1 ~]# [ 2!= 2 ] && echo 1 || echo 0  #<==比較不相等符號也是正確的。
0

二元數字在[]中使用-gt、-le類符號的比較。

[root@node1 ~]# [ 2 -gt 1 ] && echo 1 || echo 0
1  #<==2大於1成立,輸出1。
[root@node1 ~]# [ 2 -ge 1 ] && echo 1 || echo 0
1  #<==2大於等於1成立,輸出1。
[root@node1 ~]# [ 2 -le 1 ] && echo 1 || echo 0
0  #<==2小於等於1不成立,輸出0。
[root@node1 ~]# [ 2 -lt 1 ] && echo 1 || echo 0
0  #<==2小於1不成立,輸出0。

二元數字配合不同種類的操作符在[[]]中的比較。

[root@node1 ~]# [[ 5 > 6 ]] && echo 1 || echo 0
0  #<==5大於6不成立,輸出0。
[root@node1 ~]# [[ 5 < 6 ]] && echo 1 || echo 0
1  #<==5小於6成立,輸出1。
[root@node1 ~]# [[ 5!= 6 ]] && echo 1 || echo 0
1  #<==5不等於6成立,輸出1。
[root@node1 ~]# [[ 5 = 6 ]] && echo 1 || echo 0
0  #<==5等於6不成立,輸出0。
[root@node1 ~]# [[ 5 -gt 6 ]] && echo 1 || echo 0
0  #<==5大於6不成立,輸出0。
[root@node1 ~]# [[ 5 -lt 6 ]] && echo 1 || echo 0
1  #<==5小於6成立,輸出1。
[root@node1 ~]# [[ 65 > 66 ]] && echo 1 || echo 0
0  #<==65大於66不成立,輸出0。
[root@node1 ~]# [[ 65 < 66 ]] && echo 1 || echo 0
1  #<==65小於66成立,輸出1。
[root@node1 ~]# [[ 65 = 66 ]] && echo 1 || echo 0
0  #<==65等於66不成立,輸出0。

二元數字在(())中的比較。

[root@node1 ~]# ((3>2)) && echo 1 || echo 0
1  #<==3大於2成立,輸出1。
[root@node1 ~]# ((3<2)) && echo 1 || echo 0
0  #<==3小於2不成立,輸出0。
[root@node1 ~]# ((3==2)) && echo 1 || echo 0
0  #<==3等於2不成立,輸出0。
[root@node1 ~]# ((3!==2)) && echo 1 || echo 0 #<==“!==”符號不可用,語法錯誤
bash:((:3!==2:syntax error:operand expected (error token is "=2")
0
[root@node1 ~]# ((3!=2))&& echo 1 || echo 0
1

有關[]、[[]]、(())用法的小結:

1)·整數加雙引號的比較是對的。
2)·[[]]中用類似-eq等的寫法是對的,[[]]中用類似>、<的寫法也可能不對,有可能會只比較第一位,邏輯結果不對。
3)·[]中用類似>、<的寫法在語法上雖然可能沒錯,但邏輯結果不對,可以使用=、!=正確比較。
4)·(())中不能使用類似-eq等的寫法,可以使用類似>、<的寫法。

整數變數測試實踐示例

通過[]實現整數條件測試。

[root@node1 ~]# a1=98;a2=99
[root@node1 ~]# [ $a1 -eq $a2 ] && echo 1 || echo 0 #<==測試$a1是否等於$a2
0
[root@node1 ~]# [ $a1 -gt $a2 ] && echo 1 || echo 0 #<==測試$a1是否大於$a2。
0
[root@node1 ~]# [ $a1 -lt $a2 ] && echo 1 || echo 0 #<==測試$a1是否小於$a2。
1

利用[[]]和(())實現直接通過常規數學運算子進行比較。

[root@node1 ~]# [[ $a1 > $a2 ]] && echo 1 || echo 0  #<==測試$a1是否大於$a2,儘量不用此寫法。
0
[root@node1 ~]# [[ $a1 < $a2 ]] && echo 1 || echo 0  #<==測試$a1是否小於$a2,儘量不用此寫法。
1
[root@node1 ~]# (( $a1 >= $a2 )) && echo 1 || echo 0   #<==測試$a1是否大於等於$a2,此寫法也可以。
0
[root@node1 ~]# (( $a1 <= $a2 )) && echo 1 || echo 0   #<==測試$a1是否小於等於$a2,
1

有關整數(要確認是整數,否則會報錯)的大小比較,(())語法要優於[[]],但還是推薦優先使用[],次選是(()),不推薦使用[[]]。示例如下:

[ num1 –eq num2 ]     #<==注意比較符號兩邊的空格和比較符號的寫法,必須要有空格。
(( num1 > num2 ))         #<==比較符號兩邊無需空格(多空格也可),使用常規數學的比較符號即可。

五、邏輯操作符

1、邏輯操作符

在[]和test中使用

-a and,與,兩端都為真,則結果為真
-o or,或,兩端有一個為真,則結果為真
!  not,非,兩端取反,則結果為真

在[[]]和(())中使用

&& and,與,兩端都為真,則結果為真
|| or,或,兩端有一個為真,則結果為真
!   not,非,兩端取反,則結果為真
1)·邏輯操作符前後的表示式是否成立,一般用真假來表示。
2)·“!”的中文意思是反,即與一個邏輯值相反的邏輯值。
3)·-a的中文意思是“與”(and或&&),前後兩個邏輯值都為“真”,綜合返回值才為“真”,反之為“假”。
4)·-o的中文意思是“或”(or或||),前後兩個邏輯值只要有一個為“真”,返回值就為“真”。
5)·連線兩含[]、test或[[]]的表示式可用&&或||。

2、邏輯操作符運算規則

-a和&&的運算規則:只有邏輯操作符兩端的表示式都成立時才為真;真(true)表示成立,對應的數字為1;假(false)表示不成立,對應的數字為0

[root@node1 ~]# [ -f /etc/hosts -a -f /etc/services ] && echo 1 || echo 0
#<==單中括號檔案測試。
1
[root@node1 ~]# [[ -f /etc/hosts && -f /etc/services ]] && echo 1 || echo 0
#<==雙中括號檔案測試。
1
使用-a和&&的綜合表示式結果,相當於將兩端表示式結果的對應數字(0或1)相乘。
當左邊為真,右邊為假的時候,相乘結果為1*0=0,總結果為假(0)。
當左邊為假,右邊為真的時候,相乘結果為0*1=0,總結果依然為假(0)。
當左邊為真,右邊也為真的時候,相乘結果為1*1=1,總結果為真(1)。
當左邊為假,右邊也為假的時候,相乘結果為0*0=0,總結果為假(0)。
簡單表示為:
and結果1*0=0 假
and結果0*1=0 假
and結果1*1=1 真
and結果0*0=0 假
結論:and(&&)也稱為與,只有兩端都是1時才為真,相當於取前後表示式的交集。

-o或||兩端都是0才為假,任何一端不為0就是真,這相當於將兩邊表示式結果的對應數字(0或1)相加,對應的表示式為:

[root@node1 ~]# [ 5 -eq 6 -o 5 -gt 3 ] && echo 1 || echo 0
1
[root@node1 ~]# ((5==6||5>3)) && echo 1 || echo 0
1
-o或||的運算規則為:
當左邊為真,右邊為假的時候,相加結果為1+0=1,總結果為真(1)。
當左邊為假,右邊為真的時候,相加結果為0+1=1,總結果依然為真(1)。
當左邊為真,右邊也為真的時候,相加結果為1+1=2,總結果為真(1),非0即真。
當左邊為假,右邊也為假的時候,相加結果為0+0=0,總結果為假(0)。
簡單表示為:
or 結果1+0=1 真
or 結果1+1=2 真(非0即為真)
or 結果0+1=1 真
or 結果0+0=0 假
結論:or(||)也稱為或,它的兩端表示式的結果都是0時才為假,不為0就是真。相當於對前後表示式結果取並集。

案例

[]裡的邏輯操作符配合檔案測試表達式使用的示例。

[root@node1 ~]# f1=/etc/rc.local;f2=/etc/services
#<==定義f1和f2兩個變數,分別賦值兩個已知存在的檔案路徑。
[root@node1 ~]# echo -ne "$f1 $f2\n"  #<==測試輸出f1和f2兩個變數的值。
/etc/rc.local /etc/services
[root@node1 ~]# [ -f "$f1" -a -f "$f2" ] && echo 1 || echo 0 #<==[]裡使用-a(and)。
#<==測試f1和f2兩個變數值是否都為普通檔案,如果成立,則輸出1,否則輸出0。
1
[root@node1 ~]# [ -f "$f1" -o -f "$f222" ] && echo 1 || echo 0
#<==測試f1和f222兩個變數值是否都為普通檔案,如果成立,則輸出1,否則輸出0;f222變數是未定義的,但是f1變數是有的,並且是普通檔案,-o兩邊有一個表示式成立(即為真),因此輸出1。
1
[root@node1 ~]# [ -f "$f111" -o -f "$f222" ] && echo 1 || echo 0
#<==測試f111和f222兩個變數值中是否有一個為普通檔案,如果成立,則輸出1,否則輸出0。
0 #<==f111和f222兩個變數都是未定義的,因此輸出0。
[root@node1 ~]# [ -f "$f1" && -f "$f2" ] && echo 1 || echo 0 #<==這是錯誤語法,[]中不能用&&或||-bash:[:missing `]'
0
[root@node1 ~]# [ -f "$f1" ] && [ -f "$f2" ] && echo 1 || echo 0
#<==如果在[]中想使用&&,則這樣用。
1

[[]]裡邏輯操作符配合字串的條件表示式的測試示例。

[root@node1 ~]# a="ywx";b="kaka"  #<==定義a和b兩個變數,賦值兩個已知的字串。
[root@node1 ~]# echo -ne "$a $b\n"  #<==測試輸出a和b兩個變數的值。
ywx kaka
[root@node1 ~]# [[!-n "$a" && "$a" = "$b" ]] && echo 1 || echo 0
#<== [[]]內部用&&或||。
#<==測試$a長度不為0是否成立,並且$a等於$b是否成立,兩個表示式是否同時成立。
0 #<==因為$a長度不為0成立,結果為1,加上前面“!”取反,就是不成立,結果變為0。$a等於$b成立,結果為1,兩個表示式綜合起來0*1=0,因此不成立,輸出0。
[root@node1 ~]# [[ -z "$a" || "$a"!= "$b" ]] && echo 1 || echo 0
#<== [[]]中||的使用。
1
[root@node1 ~]# [[ -z "$a" -o "$a"!= "$b" ]] && echo 1 || echo 0
#<== [[]]內部用-a或-o會報錯。
-bash:syntax error in conditional expression
-bash:syntax error near `-o'

(())裡邏輯操作符配合整數的條件表示式測試示例。

[root@node1 ~]# m=21;n=38
[root@node1 ~]# ((m>20&&n>30)) && echo 1 || echo 0 #<== (())內部用&&或||1
[root@node1 ~]# ((m<20||n>30)) && echo 1 || echo 0
1
[root@node1 ~]# ((m<20||n<30)) && echo 1 || echo 0
0
[root@node1 ~]# ((m<20 -a n<30)) && echo 1 || echo 0
#<== (())內部用-a或-o也會報語法錯誤。
-bash:((:m<20 -a n<30:syntax error in expression (error token is "n<30")
0

使用多個[]號,並通過與或非進行混合測試。

[root@node1 ~]# m=21;n=38
[root@node1 ~]# [ $m -gt 20 -a $n -lt 30 ] && echo 1 || echo 0
0
[root@node1 ~]# [ $m -gt 20 ]||[ $n -lt 30 ] && echo 1 || echo 0
#<==多個[]號之間用&&或||連線。
1

總結

1)·“-a”和“-o”邏輯操作符號需要用於[]中。
2)·“&&”和“||”邏輯操作符號可用於[[]]或(())中,也可以在外部連線多個[]。
3)·注意,在[]和[[]]的兩端及比較符號的兩端,必須要有空格,但是對於(())不需要。

邏輯操作符企業案例

輸入或通過命令列傳入一個字元或數字,如果傳入的數字等於1,就列印1;如果等於2,就列印2;如果不等於1也不能於2,就提示輸入不對,然後退出程式。

參考答案1:使用read讀入內容方案。

#!/bin/sh
echo -n "pls input a char:" #<==列印提示字串,-n表示不換行。
read var #<==讀取使用者的輸入並賦值給var變數。
[ "$var" == "1" ] &&{ #<==條件表示式判斷,看變數是否等於1,注意普通字元比較多地用字串比較的語法,即加雙引號比較,而不是使用整數比較的語法,整數比較容易出錯,除非確定是整數。
    echo 1
    exit 0 #<==每個邏輯正確,則以返回值0退出指令碼,從而避免執行指令碼後面無用的程式碼。
}
[ "$var" == "2" ] &&{ #<==條件表示式判斷,看變數是否等於2。
    echo 2
    exit 0
}
[ "$var"!= "2" -a "$var"!= "1" ] &&{  #<==條件表示式加邏輯操作符判斷,看變數是否不等於2,並且不等於1,如果都成立,則執行命令。
    echo error
    exit 0
}

參考答案2:使用指令碼命令列傳參讀入內容的解決方案。

#!/bin/sh
var=$1 #<==將上文的read讀入資訊,改為指令碼傳參,接收指令碼的第一個引數$1賦值給var。
[ "$var" == "1" ] &&{
    echo 1
    exit 0
}
[ "$var" == "2" ] &&{
    echo 2
    exit 0
}
[ "$var"!= "2" -a "$var"!= "1" ] &&{
    echo error
    exit 0
}

開發Shell指令碼,分別實現以指令碼傳參和read讀入的方式比較兩個整數的大小。用條件表示式(禁止用if)進行判斷並以螢幕輸出的方式提醒使用者比較的結果。注意:一共是開發兩個指令碼。在用指令碼傳參和read讀入的方式實現時,需要對變數是否為數字及傳參個數是否正確給予提示。

參考答案1:採用read方法。

#!/bin/sh
read -p "Pls input two num:" a b  #<==請求使用者輸入兩個引數,讀入後分別賦值給變數a和b。
#no1
[ -z "$a" ]||[ -z "$b" ] &&{  #<==如果$a變數長度為0或$b變數長度為0,即任何一個
                                      變數為空,則執行命令。
    echo "Pls input two num again." #<==a或b沒值,表示使用者輸入錯誤,給出提示。
    exit 1 #<==以返回值1退出指令碼。
}
#no2
expr $a + 10 &>/dev/null #<==判斷$a是否為整數,不輸出任何資訊。前文已講解過了expr
判斷整數的方式。
RETVAL1=$? #<==將返回值賦值給RETVAL1,後面會用這個返回值做判斷。
expr $b + 10 &>/dev/null #<==判斷$b是否為整數,不輸出任何資訊。
RETVAL2=$? #<==將返回值賦值給RETVAL2,後面會用這個返回值做判斷。
test $RETVAL1 -eq 0 -a $RETVAL2 -eq 0||{ #<==利用test進行返回值是否為0的判斷。如果有一個返回值不為0,則說明有一個變數不為整數,不合要求,列印提示後退出。
    echo "Pls input two "num" again."
    exit 2
}
#no3
[ $a -lt $b ] &&{  #<==整數比較,$a是否小於$b。
    echo "$a < $b"
    exit 0
}
#no4
[ $a -eq $b ] &&{  #<==整數比較,$a是否等於$b。
    echo "$a = $b"
    exit 0
}
#no5
[ $a -gt $b ] &&{  #<==整數比較,$a是否大於$b。
    echo "$a > $b"
}

參考答案2:通過命令列傳參的方法實現。

#!/bin/sh
a=$1 #<==將上文的read讀入資訊改為指令碼傳參,接收指令碼的第一個引數$1賦值給a。
b=$2 #<==將上文的read讀入資訊改為指令碼傳參,接收指令碼的第二個引數$2賦值給b。
#no1
[ $# -ne 2 ] &&{ #<==傳參專用判斷手法,判斷傳參個數是否為兩個。
    echo "USAGE:$0 NUM1 NUM2" #<==傳參不合要求,給出用法提示。
    exit 1 #<==以返回值1退出指令碼。
}
#no2
expr $a + 10 &>/dev/null    #<==整數判斷,前文已講。
RETVAL1=$?
expr $b + 10 &>/dev/null    #<==整數判斷,前文已講。
RETVAL2=$?
test $RETVAL1 -eq 0 -a $RETVAL2 -eq 0||{
    echo "Pls input two "num" again."
    exit 2
}
#no3
[ $a -lt $b ] &&{
    echo "$a < $b"
    exit 0
}
#no4
[ $a -eq $b ] &&{
    echo "$a = $b"
    exit 0
}
#no5
[ $a -gt $b ] &&{
    echo "$a > $b"
}

六、測試表達式test、[]、[[]]、(())的區別總結