2013年11月25日 星期一

bash 判斷式

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

參考:
  1. 善用判斷式 [鳥哥的 Linux 私房菜]
  2. 真假值判斷 [Shell 設計入門 by 臥龍小三] mirror
  3. Shell Script 文章
  4. man bash 的  CONDITIONAL EXPRESSIONS 段落
  5. http://mywiki.wooledge.org/BashFAQ/031
  6. https://stackoverflow.com/questions/3427872/whats-the-difference-between-and-in-bash

沒有留言:

張貼留言

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...