鍍金池/ 教程/ Linux/ shell 學習第二十七天----退出狀態(tài)和 if 語句
shell 學習四十一天----列出文件 ls 和 od 命令
shell 學習小結(jié)
shell 學習第二十八天----case 語句
shell 學習四十四天----尋找文件
shell 學習三十五天----波浪號展開與通配符
shell 學習三十八天----執(zhí)行順序和 eval
shell 學習四十八天----文件校驗和匹配
shell 學習四十天----awk 的驚人表現(xiàn)
shell 學習第十一天----sed 正則的精確控制
shell 學習第十七天----awk 命令
shell 學習三十九天----內(nèi)建命令
shell 學習四十五天----xargs
shell 學習三十七天----引用
shell 學習第十六天----join 練習
shell 學習第二十四天----提取開頭或結(jié)尾數(shù)行
shell 學習第九天----分組
shell 學習第五天----基本的 I/O 重定向
shell 學習第十五天----使用 cut 選定字段
shell 學習四十六天----文件系統(tǒng)的空間信息 df 和 du 命令
shell 學習第八天----擴展正則表達式 (ERE)
shell 學習第十九天----文本塊排序
shell 學習第二十一天----重新格式化段落
shell 學習三十六天----命令替換
shell 學習第二十天----sort 的其他內(nèi)容以及 uniq 命令
shell 學習四十二天----使用 touch 更新文件時間
shell 學習五十一天----top 命令查看進程列表
shell 學習第一天
shell 學習五十四天----進程系統(tǒng)調(diào)用的追蹤 strace
shell 學習五十天----查看進程 ps 命令
shell 學習第二十七天----退出狀態(tài)和 if 語句
shell 學習第二十三天----打印
shell 學習三十三天----關于重定向
shell 學習四十九天----進程建立
shell 學習第三十天----break,continue,shift,getopts
shell 學習五十五天----進程記賬
shell 學習總結(jié)一
shell 學習第二十六天----變量與算數(shù)
shell 學習第二十二天----計算行數(shù), 字數(shù)以及字符數(shù)
shell 學習五十八天----/proc 文件系統(tǒng)
shell 學習第二十五天----神器的管道符
shell 學習第三十二天----read 讀取一行
sheel 學習第三天
shell 學習----小結(jié)
shell 學習第十八天----文本排序
shell 學習第三十一天----函數(shù)問題
shell 學習第十天----sed 查找與替換
shell 學習四十三天----臨時性文件的建立與使用
shell 學習四十七天----文件比較 cmp,diff,patch
shell 學習三十四天----printf 詳解
shell 學習五十七天 ----linux 任務管理,針對上一講的總結(jié)和擴展
shell 學習第六天----小結(jié)
shell 學習第十三天----sed 案例分析
shell 學習第七天----基礎正則表達式 (BRE)
shell 學習第十二天----行與字符串
shell 學習小結(jié)四
shell 學習第二十九天----循環(huán)
shell 學習五十二天----刪除進程 kill 命令
shell 學習五十六天----延遲進程調(diào)度
shell 學習第四天----華麗的 printf 輸出
shell 學習第十五天----join 連接字段
shell 學習完結(jié)篇----希望你能看到
shell 學習第二天
shell 學習五十三天----捕獲信號 trap

shell 學習第二十七天----退出狀態(tài)和 if 語句

退出狀態(tài)

每一條命令;不管是內(nèi)置的,shell 函數(shù),還是外部的,當它退出時,都會返回一個小的整數(shù)值給引用它的程序,這就是大家所熟知的程序的退出狀態(tài)。在 shell 下執(zhí)行進程是,有很多方式可取用程序的退出狀態(tài)。

以管理來說,退出狀態(tài)為 0 表示 “成功”,也就是,程序執(zhí)行完成且為遭遇到任何問題。其他任何的退出退出狀態(tài)都為失敗。內(nèi)置變量?(使用命令 echo $?) 查看上一條命令的退出狀態(tài)。

案例:當你輸入 ls -l /dev/null 時。
輸出:crw-rw-rw- 1 root root 1,3 6 月 25 15:41 /dev/null
接著使用命令:echo $?
輸出為 0
接著使用命令:ls foo 輸出:ls:無法訪問 foo:沒有那個文件或目錄
echo $?
輸出:2
表示沒有成功的執(zhí)行。

POSIX 的結(jié)束狀態(tài)

值
意義
0
命令成功地退出
\>0
在重定向或單詞展開期間 (~,變量,命令,算數(shù)展開,以及單詞切割) 失敗
1-125
命令不成功的退出。特定的退出值的含義,是由各個單獨的命令定義的。
126
命令找到了,但文件無法執(zhí)行
127
命令沒找到
\>128
命令因受到信號而死亡

POSIX 留下退出狀態(tài) 128 未定義,僅要求他表示某種失敗。因為只有低位的 8 個位會返回給父進程,所以大于 255 的退出狀態(tài)都會替換成該值除以 256 之后的余數(shù)。

在 shell 腳本可以使用 exit 命令傳遞一個退出之給踏的調(diào)用者。只要將一個數(shù)字傳遞給它,作為一個參數(shù)即可。腳本會立即退出,并且調(diào)用者會受到該數(shù)字且作為腳本的退出值。

說白了 exit 就是退出當前的 shell,在 shell 腳本中可以終止當前腳本執(zhí)行。

exit

語法:
exit [exit-value]
用途: 目的是從 shell 腳本返回一個退出狀態(tài)給腳本的調(diào)用者。
主要選項:

行為模式: 如果沒有提供,則以最后一個執(zhí)行命令的退出狀態(tài)作為默認的退出狀態(tài)。如果這就是你要的,則最好明白的在 shell 腳本里這么寫:exit $?

案例一:exit
輸出為 logout,表示退出當前 shell

案例二:腳本代碼 cd $(dirname $0) || exit 1
進入腳本所在目錄,否則退出

案例三:腳本中判斷參數(shù)數(shù)量,不匹配就打印使用方式,退出
代碼:

if ["$#" -ne "2"]; then  
          echo "usage:$0 <area> <hours>"  
              exit 2  
          fi  

案例四:在腳本里,退出時刪除臨時文件
代碼:trap “入門 -rf tempfile;echo Bye.” exit

案例五:檢查上一行的退出碼 代碼:

EXCODE=$?
 if ["$EXCODE" == "0"]; then
         echo "O.K"
      fi

if-elif-else-fi 語句
if 語法:

  1. 單分支的 if 語句 if 條件測試命令 then 命令序列 fi
  2. 雙分支的 if 語句 if 條件測試命令 then 命令序列 1 else 命令序列 2 fi
  3. 多分支的 if 語句 (elif 可以嵌套多個,一般多了用 case 表達) if 條件測試命令 1 then 命令序列 1 elif 條件測試命令 2 then 命令序列 2 ......... else 命令序列 n fi
if pipeline
[pipeline...]
then
statement-if-true-1
elif pipeline
[pipeline...]
then 
statement-iftrue2
else
statement-if-all-else-fails
if

使用方括號作為開始與結(jié)束的關鍵字將語句組織起來。

案例 1:提示用戶指定備份目錄的路徑,若目錄存在則顯示信息跳過,否則顯示相應提示信息,并創(chuàng)建該目錄。 bash 代碼:

\#!/bin/bash
read -p "what is your backup directoy :" BakDir
if [-d $BakDir];then
        echo "$BakDir alerdy exist"
else
        echo "$BakDir is not exist,will make it"
        mkdir $BakDir
fi

案例 2:統(tǒng)計當前登錄到系統(tǒng)中的用戶數(shù)量,若判斷是否超過三個,若是則顯示實際數(shù)量并給出警告信息,否則列出登錄的用戶賬戶名稱及所在終端

bash 代碼:

UserNum='who | wc -l'
if [$UserNum -gt 3];
        then
        echo "Alert, too many login users (Total:$UserNum)."
else
        echo "Login Users:"
        who | awk '{print $1,$2}'
fi

注意:

  1. if 與 [ 之間必須有空格
  2. [ ] 與判斷條件之間也必須有空格
  3. ] 與; 之間不能有空格

邏輯的 not,and 與 or

“如果 john 不在家,則...” ,在 shell 下這種情況的做法是: 將驚嘆號放在管道前:

if ! grep pattern myfile > /dev/null
then
模式不在這里
fi

“如果 john 在家,且他不忙,則....”,使用邏輯 and。

if grep pattern1 myfile && grep pattern2 myfile
then 
myfile 包含兩種模式
fi

相對的,|| 運算符則用來測試兩個條件中是否有一個為真。:

if grep pattern1 myfile || grep pattern2 myfile
then 
myfile 包含兩種模式之一
fi

邏輯 and 和 or 都是快捷運算符,即當判斷出整個語句塊的真?zhèn)螘r,shell 會立即停止執(zhí)行命令。舉例來說,在 command1&&command2 下,如果 aommand1 失敗,則整個結(jié)果不可能為真,所以 command2 也不會被執(zhí)行;以此類推,command1||command2 指的是: 如果 command1 成功,那么也沒有理由執(zhí)行 command2。

不要嘗試過度” 簡練” 未使用 && 和 || 來取代 if 語句。我們不反對簡短且簡單的事情,例如:

命令:who | grep root > /dev/null && echo root is login on root is login on
輸出:root is login on
分析:上面的命令實際做法是: 執(zhí)行 who | grep... 且如果成功,就顯示信息。而我們曾見過廠商提供 shell 腳本,所使用的是這樣的結(jié)構(gòu):

some_command &&{
one command
a decond command
and a third command
}

這個命令的意思是說將所有的語句塊放在一塊,只有在 some_command 成功時他們才被執(zhí)行。使用 if 可以讓他更簡潔:

if some_command
then
one command
a second command
and a third command
fi

最后在判斷語句中常用的運算符:

1、字符串判斷

str1 = str2      當兩個串有相同內(nèi)容、長度時為真
str1 != str2      當串 str1 和 str2 不等時為真
-n str1        當串的長度大于 0 時為真 (串非空)
-z str1        當串的長度為 0 時為真 (空串)
str1   當串 str1 為非空時為真

2、數(shù)字的判斷

int1 -eq int2    兩數(shù)相等為真
int1 -ne int2    兩數(shù)不等為真
int1 -gt int2int1 大于 int2 為真
int1 -ge int2int1 大于等于 int2 為真
int1 -lt int2int1 小于 int2 為真
int1 -le int2int1 小于等于 int2 為真

3、文件的判斷

-r file     用戶可讀為真
-w file     用戶可寫為真
-x file     用戶可執(zhí)行為真
-f file     文件為正規(guī)文件為真
-d file     文件為目錄為真
-c file     文件為字符特殊文件為真
-b file     文件為塊特殊文件為真
-s file     文件大小非 0 時為真
-t file     當文件描述符 (默認為 1) 指定的設備為終端時為真

4、復雜邏輯判斷

-a         與
-o        或
!        非

test 命令

test 命令可以處理 shell 腳本里的各類工作。它產(chǎn)生的不是一般輸出,而是可使用的退出狀態(tài)。test 接受各種不同的參數(shù),可控制它要執(zhí)行哪一種測試。

test 命令有另一種形式:[...],這種永福的作用完全與 test 命令一樣。因此,下面這兩個案例表達的意思相同

if test "$str1"="$str2"
then
...
fi
和
if ["$str1" = "$str2" ]
then
...
fi
一樣

test 的語法:

test [expression] [[expression] ]

用途:

為了測試 shell 腳本里的條件,通過退出狀態(tài)返回其結(jié)果。要特別注意的是:這個命令的第二種形式,方括號根據(jù)字面意義逐字的輸入,且必須與括起來的 expression 以空白隔開。

主要選項: 和使用用于 if 的選項一致。 其中

選項
含義
string 
如果... 則為真
-b file
file 是塊設備文件
-d file
file 是目錄
-c file
file 是字符設備文件
-e file
file 存在
-f file
file 為一般文件
-g file
file 有設置他的 setgid 位
-h file
file 是一符號鏈接
-L file
file 是一符號鏈接 (等同于 -h)
-n string
string 是非 null
-p file
file 是一命名的管道 (FIGO 文件)
-r file
file 是可讀的
-S file
file 是 socket
-s file
file 不是空的
-t n
文件描述符 n 指向一終端
-u file
file 有設置它的 setuid 位
-w file
file 是可寫入的
-x file
file 是可執(zhí)行的,或 file 是可被查找的目錄
-z string
string 為 null
s1=s2 或者 s1!=s2
字符串相不相等
n1 -eq n2
整數(shù) n1 等于 n2
n1 -ne n2
整數(shù) n1 不等于 n2
n1 -lt n2 
n1 小于 n2
n1 -gt n2
n1 大于 n2
n1 -le n2
n1 小于或等于 n2
n1 -ge n2
n1 大于或等于 n2

案例:

bash 代碼:

\#!/bin/bash
cd /bin
if test -e ./bash   // 其實這里相當于 if [-e ./bahs]
then
        echo 'the file already exist!'
else
        echo 'the file not exist!'
fi

輸出結(jié)果為:the file already exist!

另外,shell 還提供了 -a(邏輯 AND),-o(邏輯 OR),-a 的優(yōu)先級高于 -o,而 = 與!= 優(yōu)先級則高于其他的二元運算符。

注意:在使用 -a-o(這兩個事 test 運算符) 與 &&||(這兩個事 shell 運算符) 之間有一個差異:

  • if [-n "$str" -a -f "$file" ] 一個 test 命令,兩種條件
  • if [-n "str"] && [-f "$file" ] 兩個命令,一塊接方式計算
  • if [-n "$str" && -f "$file"] 語法錯誤

第一個案例,test 會計算兩種條件。而第二個案例,shell 執(zhí)行第一個 test 命令,且只有在第一個命令是成功的情況下,才會執(zhí)行第二個命令。最后一個案例,&& 為 shell 運算符,所以它會終止第一個 test 命令,然后這個命令會抱怨它找不到結(jié)束的] 字符,且以失敗的值退出。即使 test 可以成功的退出,接下來的檢查還會失敗,因為 shell(最有可能) 找不到一個名為 -f 的命令

精簡表達式:
使用命令:[1 eq1] &&echo'OK'
輸出:ok

使用命令:[2 < 1] &&echo 'OK'
輸出:-bash:1:No such file or directory

使用命令:[2 \< 1] &&echo 'OK'這樣就可以了
使用命令:[2 -gt 1 -a 3 -lt 4]&&echo 'Ok' 輸出:Ok

使用命令:[2 -gt 1 && 3 -lt 4]&&echo 'Ok'
輸出:-bash:[:missing `]'

注意:在 [] 表達式中,常見的 >,< 需要加轉(zhuǎn)義字符,表示字符串大小比較,以 acill 碼位置作為比較。不直接支持 <> 運算符,還有邏輯運算符 ||&& 它需要用 -a[and] –o[or] 表示。
剛才使用的 [],現(xiàn)在再來看使用 [[]]

案例:

使用命令:[[2 < 3]]&&echo 'OK'
輸出 OK。

使用命令:[[2 < 3 && 4 < 5]] && echo 'ok'
輸出:ok

注意:[[]] 運算符只是 [] 運算符的擴充。能夠支持 <,> 符號運算不需要轉(zhuǎn)義符,它還是以字符串比較大小。里面支持邏輯運算符 ||&&。 bash 的條件表達式中有三個幾乎等效的符號和命令:test,[][[]]。通常,大家習慣用 if [];then 這樣的形式。而 [[]] 的出現(xiàn),根據(jù) ABS 所說,是為了兼容 >< 之類的運算符。
不考慮對低版本 bash 和對 sh 的兼容的情況下,用 [[]] 是兼容性強,而且性能比較快,在做條件運算時候,可以使用該運算符。