1. 程式人生 > >shell指令碼專家指南筆記#4_比較和測試

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路徑。
    # 具體原因不清楚,這點記住就好。