linux中shell test 條件運算式說明

來源:互聯網
上載者:User

條件運算式("CONDITIONAL EXPRESSIONS")

條件運算式用於 [[ 複合命令以及內建命令 test 和 [ 中,用來測試檔案屬性,進行字串和算術比較。運算式使用下面的單目或二進位操作構造。如果某操作的任何 file 參數的形式是
檔案符號:


在info bash裡的第“6.4 Bash Conditional Expressions”節裡開頭有一句話說明了shell條件判斷的二個機制:

Conditional expressions are used by the `[[' compound command and the
`test' and `[' builtin commands.

  

機制一:內建(builtin)的函數test(運算子[]),此部分完整的說明,可查看“4.1 Bourne Shell Builtins”

 

機制二:[[]],條件結構關健字,具體可查看“3.2.4.2 Conditional Constructs”

  

test跟[]是一回事,只不過一個以函數的形式,一個以成對操作符的形式出現,

test包含6.4節條件運算式的表達形式,

是函數就有參數,test對1、2、3.。。6等多個參數的判斷分別進行定義

  

而[[]],大部分的功能跟[]是一樣的,可以簡單理解成[]的擴充,但對於參數的判斷定義上,比test有更完整的定義,不容易出現[]中的錯誤

比如在-eq比較的右操作符中,[]要求右操作符不為空白,否則報錯,返回2,而[[]]則不會:

[root@localhost tmp]# [ 1 -eq  $a ]    
+ '[' 1 -eq ']'
-bash: [: 1: unary operator expected
[root@localhost tmp]# echo $?     
+ echo 2
2
[root@localhost tmp]# [[ 1 -eq  $a ]]
+ [[ 1 -eq '' ]]
[root@localhost tmp]# echo $?       
+ echo 1
1

 

這也是很多程式員喜歡用[[]]的原因,不容易出錯

  

相比test的表達能力,[[]]擴充了二個功能

1:pattern match,萬用字元匹配,採用雙等號“==”

2:regex match,正則匹配,採用“=~”運算子號

 

首先說明下萬用字元匹配:

先說明一下[]裡的==運算,[]也包括==比較,用於字串相等比較

同樣,==號在這裡也不允許右操作符為空白,否則報錯

[root@localhost tmp]# [ "abc" == $a  ] 
+ '[' abc == ']'
-bash: [: abc: unary operator expected

解決辦法是加個引號

[root@localhost tmp]# [ "abc" == "$a"  ]
+ '[' abc == '' ']'

 

而[[]]裡的==,在3.2.4.2 裡有介紹

When the `==' and `!=' operators are used, the string to the right
     of the operator is considered a pattern and matched according to
     the rules described below in *Note Pattern Matching::。。。

Any part of the pattern may be quoted
     to force it to be matched as a string.

 

這一段說明至少要注意二點

1:[[]]裡的==運算子,把所有右操作符都看做是一個pattern,

==實際上不只是簡單字串比較,而是pattern match,即萬用字元匹配,具體的規則可以參考

 3.5.8.1 Pattern Matching

 

2:最後一句:引號可以直接定義字串,在3.5.8.1裡也有一句話:The special pattern
characters must be quoted if they are to be matched literally.

即:pattern特殊字元為字元在引號裡取消特殊定義

 

這也就能解釋下邊的二個例子的差別了:

[root@localhost tmp]# set -x
+ set -x
[root@localhost tmp]# [[ abc == a*c ]]
+ [[ abc == a*c ]]
[root@localhost tmp]# echo $?        
+ echo 0
0
[root@localhost tmp]# [[ abc == "a*c" ]]
+ [[ abc == /a/*/c ]]
[root@localhost tmp]# echo $?          
+ echo 1
1

 

另外需要留意下:

在[[裡,文檔中提到

Word splitting and filename expansion are not
     performed on the words between the `[[' and `]]'; tilde expansion,
     parameter and variable expansion, arithmetic expansion, command
     substitution, process substitution, and quote removal are
     performed.


也就是說,在[[裡,不進行bash命令解析中的“文字分割Word splitting ” 和 “檔案名稱擴充filename expansion ”
但還是進行了 “~符號擴充,參數和變數擴充,算術擴充,命令替換,進程替換,引號去除”

所以不必擔心上邊例子中,a*b是否會擴充成目錄下的檔案名稱。

 

 

至於=~正則匹配,就沒有什麼特別是的了,右運算元直接定義成一個正則式子即是,這裡正則的引號可用可不用(不能用/)

因為在 “quote removal ”環節,對非擴充出來的引號做了去除處理,實際上有加引號與不加引號是一樣的結果

[root@localhost tmp]# [[ abc =~ 'ab*c' ]] 
+ [[ abc =~ ab*c ]]
[root@localhost tmp]# echo $?           
+ echo 0
0
[root@localhost tmp]# [[ abc =~ "ab*c" ]] 
+ [[ abc =~ ab*c ]]
[root@localhost tmp]# echo $?
+ echo 0
0
[root@localhost tmp]# [[ abc =~ ab*c ]] 
+ [[ abc =~ ab*c ]]
[root@localhost tmp]# echo $?         
+ echo 0
0
[root@localhost tmp]# [[ abc =~ /ab*c/ ]]
+ [[ abc =~ /ab*c/ ]]
[root@localhost tmp]# echo $?           
+ echo 1
1

例子

[root@LAMP test]# help test
test: test [expr]
    Evaluate conditional expression.
    Exits with a status of 0 (true) or 1 (false) depending on
    the evaluation of EXPR.  Expressions may be unary or binary.  Unary
    expressions are often used to examine the status of a file.  There
    are string operators as well, and numeric comparison operators.
   
    File operators:
   
      -a FILE True if file exists.
      -b FILE True if file is block special.
      -c FILE True if file is character special.
      -d FILE True if file is a directory.
      -e FILE True if file exists.
      -f FILE True if file exists and is a regular file.
      -g FILE True if file is set-group-id.
      -h FILE True if file is a symbolic link.
      -L FILE True if file is a symbolic link.
      -k FILE True if file has its `sticky' bit set.
      -p FILE True if file is a named pipe.
      -r FILE True if file is readable by you.
      -s FILE True if file exists and is not empty.
      -S FILE True if file is a socket.
      -t FD   True if FD is opened on a terminal.
      -u FILE True if the file is set-user-id.
      -w FILE True if the file is writable by you.
      -x FILE True if the file is executable by you.
      -O FILE True if the file is effectively owned by you.
      -G FILE True if the file is effectively owned by your group.
      -N FILE True if the file has been modified since it was last read.
   
      FILE1 -nt FILE2  True if file1 is newer than file2 (according to
  modification date).
   
      FILE1 -ot FILE2  True if file1 is older than file2.
   
      FILE1 -ef FILE2  True if file1 is a hard link to file2.
   
    String operators:
   
      -z STRING      True if string is empty.
   
      -n STRING
  STRING      True if string is not empty.
   
      STRING1 = STRING2
True if the strings are equal.
      STRING1 != STRING2
True if the strings are not equal.
      STRING1 < STRING2
True if STRING1 sorts before STRING2 lexicographically.
      STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.
   
    Other operators:
   
      -o OPTION      True if the shell option OPTION is enabled.
      ! EXPR  True if expr is false.
      EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
      EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
   
      arg1 OP arg2   Arithmetic tests.  OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
   
    Arithmetic binary operators return true if ARG1 is equal, not-equal,
    less-than, less-than-or-equal, greater-than, or greater-than-or-equal
    than ARG2.
   
    Exit Status:
    Returns success if EXPR evaluates to true; fails if EXPR evaluates to
    false or an invalid argument is given.
    -a file

相關參考 


如果 file 存在則為真。
-b file
如果 file 存在且為塊裝置則為真。
-c file
如果 file 存在且為字元裝置則為真。
-d file
如果 file 存在且是一個目錄則為真。
-e file
如果 file 存在則為真。
-f file
如果 file 存在且為普通檔案則為真。
-g file
如果 file 存在且是設定組ID的 (sgid) 則為真。
-h file
如果 file 存在且為符號連結則為真。
-k file
如果 file 存在且設定了 ‘‘sticky’’ 位 (粘滯位) 則為真。
-p file
如果 file 存在且是一個具名管道 (FIFO) 則為真。
-r file
如果 file 存在且可讀則為真。
-s file
如果 file 存在且大小大於零則為真。
-t fd  如果檔案描述符 fd 是開啟的且對應一個終端則為真。
-u file
如果 file 存在且是設定使用者ID的 (suid) 則為真。
-w file
如果 file 存在且可寫則為真。
-x file
如果 file 存在且可執行則為真。
-O file
如果 file 存在且為有效使用者ID所擁有則為真。
-G file
如果 file 存在且為有效組ID所擁有則為真。
-L file
如果 file 存在且為符號連結則為真。
-S file
如果 file 存在且為通訊端則為真。
-N file
如果 file 存在且上次讀取後被修改過則為真。
file1 -nt file2
如果 file1 比 file2 要新 (根據修改日期),或者如果 file1 存在而 file2 不存在,則為真。
file1 -ot file2
如果 file1 比 file2 更舊,或者如果 file1 不存在而 file2 存在,則為真。
file1 -ef file2
如果 file1 和 file2 指的是相同的裝置和 inode 號則為真。
-o optname
如果啟用了 shell 選項 optname 則為真。參見下面對內建命令 set 的 -o 選項的描述中的選項列表。
-z string
如果 string 的長度為 0 則為真。
-n string
string 如果 string 的長度非 0 則為真。
string1 == string2
如果字串相等則為真。= 可以用於使用 == 的場合來相容 POSIX 規範。
string1 != string2
如果字串不相等則為真。
string1 < string2
如果 string1 在當前語言環境的字典順序中排在 string2 之前則為真。
string1 > string2
如果 string1 在當前語言環境的字典順序中排在 string2 之後則為真。
arg1 OP arg2
OP 是 -eq, -ne, -lt, -le, -gt, 或 -ge 之一。這些算術二進位操作返回真,如果 arg1 與 arg2 分別是相等,不等,小於,小於或等於,大於,大於或等於關係 。  Arg1   和
arg2 可以是正/負整數。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.