bash 判斷式 (Conditional Expression) 用在內建指令 test 和 [、以及複合指令 [[ 來測試檔案屬性、進行字串或算術比較。[ 可以視為傳統 test 指令一樣的指令行,但最後要有引數 ]。由於每一項是引數,特殊字元要跳脫,但符合 POSIX 可攜性較好。[[ 算是 [ 的進階版,對應以 ]] 結束,不進行 Word splitting 和 pathname expansion,另外還有 Pattern Matching 功能。
真假值判斷可針對字串、整數、及檔案三大類,並且可以邏輯結合起來。
字串比較
[ str1 = str2 ]
[ str1 == str2 ] |
字串相等 |
POSIX 相容 test 指令要用「=」。
|
[ str1 != str2 ] |
字串不相等 |
|
[ str1 \> str2 ] |
字串大於 |
「\」是 shell 的跳脫字元,消除「>」「<」輸出入轉向之意。 |
[ str1 \< str2 ] |
字串小於 |
[ -z str ] |
空字串,字串長度為 0 |
|
[ str ]
[ -n "str" ] |
非空字串,字串長度大於 0 |
兩者結果有些不一樣,似乎 -n 字串前後要加 " 才會對 |
下列都是判斷空字串:
[ "$var" = "" ]
[ ! "$var" ]
[ -z "$var" ]
[ "X${var}" = "X" ]
排序按照 lexicographical,[[ 指令用照
locale 排序,test 指令用 ASCII 順序。
當 == (或 =) 或 != 用在 [[ 指令,右邊是 pattern 進行 Pattern Matching,如同啟用選項
extglob。如果啟用選項 nocasematch,比對不分大小寫。pattern 任何部份可以 quoted 來強迫直接字串比對。
整數比較
[ n1 -eq n2 ] |
相等 |
[ n1 -ne n2 ] |
不相等 |
[ n1 -gt n2 ] |
大於 |
[ n1 -ge n2 ] |
大於等於 |
[ n1 -lt n2 ] |
小於 |
[ n1 -le n2 ] |
小於等於 |
若要用「<」、「>」、「<=」、「>=」來比較數字,則判斷式需擺在 (( )) 中,如:(( "982" > "24" ))
檔案測試
判斷檔案是否存在,或測試檔案的屬性,如類型或權限等。
[ -a file ] |
檔案存在 (和 -e 有何不同?) |
[ -b file ] |
存在為 block 裝置 |
[ -c file ] |
存在為 character 裝置 |
[ -d file ] |
存在為目錄 |
[ -e file ] |
檔名存在 |
[ -f file ] |
存在為一般檔案 |
[ -g file ] |
檔案存在且 set-group-id |
[ -h file ] |
檔案為 symbolic link (和 -S 有何不同?) |
[ -k file ] |
存在且有設 sticky bit |
[ -p file ] |
存在為 named pipe (FIFO) |
[ -r file ] | 存在為可讀 |
[ -s file ] |
存在為非空檔案 |
[ -t fd ] | file descriptor fd is open and refers to a terminal |
[ -u file ] |
存在且 set-user-id |
[ -w file ] |
存在為可寫 |
[ -x file ] |
存在為可執行 |
[ -G file ] |
存在為 effective group id 擁有 |
[ -L file ] |
存在為 symbolic link |
[ -N file ] |
存在,且上次讀取後有更改 |
[ -O file ] |
存在為擁有者 |
[ -S file ] |
存在為 socket |
[ file1 -ef file2 ] |
兩者是否為同一個檔案 (同一個 inode) |
[ file1 -nt file2 ] |
較新,或 file1 存在 file2 不存在 |
[ file1 -ot file2 ] |
較舊,或 file1 不存在 file2 存在 |
除非特指定,檔案是 symbolic link 應用在 link 的 target,而不是 link 本身。
如果檔案是 /dev/fd/n,檢查 file descriptor n。如果是 /dev/stdin、/dev/stdout、或 /dev/stderr,則分別檢查 file descriptor 0、1、或 2。
其它
-o optname:
shell 選項 optname 已啟用。
-v varname:shell 變數 varname 已設 (已指定值)。
-R varname:shell 變數 varname 已設且是 name reference.
藉由「-a」(and, 且)、「-o」(or, 或)、「!」(非) 邏輯運算,可結合好幾個真假值判斷:
[ -r filename1 -a -x filename ] ==> 若 filename1 可讀且可執行
[ -r filename1 -o -x filename ] ==> 若 filename1 可讀或可執行
[ ! -r filename1 ] ==> 若 filename1 不是可讀
[[ 不進行 Word splitting 和 pathname expansion。進行 tilde
expansion、parameter and variable expansion、arithmetic expansion、command
substitution、process substitution、和 quote removal。Conditional
operators such as -f must be unquoted to be recognized as primaries.
當 == (或 =) 或 != 用在 [[ 指令,右邊是 pattern 進行 Pattern Matching,如同啟用選項
extglob。如果啟用選項 nocasematch,比對不分大小寫。pattern 任何部份可以 quoted 來強迫直接字串比對。
另外還有額外 binary operator「=~」使用 extended regular expression (regex()),如果
regular expression syntactically 錯誤回傳 2。Substrings matched by
parenthesized subexpressions within the regular expression 存在
BASH_REMATCH 陣列,其中 index 0 是整個符合的部份,index n 是第 n 個parenthesized
subexpression 符合的部份。
用下列優先權,表示式可以結合:
( expression ):優先進行。
! expression:True if expression is false.
expression1 && expression2:expression1 false 回傳 false,否則看 expression2 是否 true。
expression1 || expression2:expression1 true 回傳 true,否則看 expression2 是否 true。
if-than-elsetest
case
參考:
- 善用判斷式 [鳥哥的 Linux 私房菜]
- 真假值判斷 [Shell 設計入門 by 臥龍小三] mirror
- Shell Script 文章
- man bash 的 CONDITIONAL EXPRESSIONS 段落
- http://mywiki.wooledge.org/BashFAQ/031
- https://stackoverflow.com/questions/3427872/whats-the-difference-between-and-in-bash