1. 程式人生 > >shell學習二十七天----退出狀態和if語句

shell學習二十七天----退出狀態和if語句

退出狀態

每一條命令;不管是內建的,shell函式,還是外部的,當它退出時,都會返回一個小的整數值給引用它的程式,這就是大家所熟知的程式的退出狀態.shell下執行程序是,有很多方式可取用程式的退出狀態.

以管理來說,退出狀態為0表示”成功”,也就是,程式執行完成且為遭遇到任何問題.其他任何的退出退出狀態都為失敗.內建變數?(使用命令echo $?)檢視上一條命令的退出狀態.

案例:當你輸入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

表示沒有成功的執行.

POSIX的結束狀態

意義

0

命令成功地退出

>0

在重定向或單詞展開期間(~,變數,命令,算數展開,以及單詞切割)失敗

1-125

命令不成功的退出.特定的退出值的含義,是由各個單獨的命令定義的.

126

命令找到了,但檔案無法執行

127

命令沒找到

>128

命令因受到訊號而死亡

POSIX留下退出狀態128未定義,僅要求他表示某種失敗.因為只有低位的8個位會返回給父程序,所以大於255的退出狀態都會替換成該值除以256之後的餘數

.

shell指令碼可以使用exit命令傳遞一個退出之給踏的呼叫者.只要將一個數字傳遞給它,作為一個引數即可.指令碼會立即退出,並且呼叫者會受到該數字且作為指令碼的退出值.

說白了exit就是退出當前的shell,shell指令碼中可以終止當前指令碼執行.

exit

語法:

exit [exit-value]

用途:

目的是從shell指令碼返回一個退出狀態給指令碼的呼叫者.

主要選項:

行為模式:

如果沒有提供,則以最後一個執行命令的退出狀態作為預設的退出狀態.如果這就是你要的,則最好明白的在shell腳本里這麼寫:exit $?

案例:exit

輸出為logout,表示退出當前shell

案例二:指令碼程式碼cd $(dirname $0) || exit 1

進入指令碼所在目錄,否則退出

案例三:指令碼中判斷引數數量,不匹配就列印使用方式,退出

程式碼:

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

使用方括號作為開始與結束的關鍵字將語句組織起來.

案例1:

提示使用者指定備份目錄的路徑,若目錄存在則顯示資訊跳過,否則顯示相應提示資訊,並建立該目錄.

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:統計當前登入到系統中的使用者數量,若判斷是否超過三個,若是則顯示實際數量並給出警告資訊,否則列出

登入的使用者賬戶名稱及所在終端

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

注意:

1if 之間必須有空格

2[ ]與判斷條件之間也必須有空格

3]之間不能有空格

邏輯的not,andor

“如果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

邏輯andor都是快捷運算子,即當判斷出整個語句塊的真偽時,shell會立即停止執行命令.舉例來說,command1&&command2,如果aommand1失敗,則整個結果不可能為真,所以command2也不會被執行;以此類推,command1||command2指的是:如果command1成功,那麼也沒有理由執行command2.

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

命令:who | grep root > /dev/null && echo root is login on               root is login on

輸出:root is login on

分析:上面的命令實際做法是:執行who | grep...且如果成功,就顯示資訊.而我們曾見過廠商提供shell指令碼,所使用的是這樣的結構:

some_command &&{

one command

a decond command

and a third command

}

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

if some_command

then

one command

a second command

and a third command

fi

最後在判斷語句中常用的運算子:

1、字串判斷

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

2、數字的判斷

int1 -eq int2    兩數相等為真
int1 -ne int2    兩數不等為真
int1 -gt int2int1大於int2為真
int1 -ge int2int1大於等於int2為真
int1 -lt int2int1小於int2為真
int1 -le int2int1小於等於int2為真

檔案的判斷

-r file     使用者可讀為真
-w file     使用者可寫為真
-x file     使用者可執行為真
-f file     檔案為正規檔案為真
-d file     檔案為目錄為真
-c file     檔案為字元特殊檔案為真
-b file     檔案為塊特殊檔案為真
-s file     檔案大小非0時為真
-t file     當檔案描述符(預設為1)指定的裝置為終端時為真

3、複雜邏輯判斷

-a         與

-o        或

!        非

test命令

test命令可以處理shell腳本里的各類工作.它產生的不是一般輸出,而是可使用的退出狀態.test接受各種不同的引數,可控制它要執行哪一種測試.

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

if test “$str1”=”$str2”

then

...

fi

if [ “$str1” = “$str2” ]

then

...

fi

一樣

test的語法:

test [expression]

[ [expression] ]

用途:

為了測試shell腳本里的條件,通過退出狀態返回其結果.要特別注意的是:這個命令的第二種形式,方括號根據字面意義逐字的輸入,且必須與括起來的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

filesocket

-s file

file不是空的

-t n

檔案描述符n指向一終端

-u file

file有設定它的setuid

-w file

file是可寫入的

-x file

file是可執行的,file是可被查詢的目錄

-z string

stringnull

s1=s2 或者s1!=s2

字串相不相等

n1 -eq n2

整數n1等於n2

n1 -ne n2

整數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

輸出結果為:the file already exist!

另外,shell還提供了-a(邏輯AND),-o(邏輯OR),-a的優先順序高於-o,=!=優先順序則高於其他的二元運算子.

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

if [ -n “$str” -a -f “$file” ] 一個test命令,兩種條件

if [-n “str”] && [ -f “$file” ] 兩個命令,一塊接方式計算

if [-n “$str” && -f ”$file”] 語法錯誤

第一個案例,test會計算兩種條件.而第二個案例,shell執行第一個test命令,且只有在第一個命令是成功的情況下,才會執行第二個命令.最後一個案例,&&shell運算子,所以它會終止第一個test命令,然後這個命令會抱怨它找不到結束的]字元,且以失敗的值退出.即使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 `]'

注意:在[] 表示式中,常見的>,<需要加轉義字元,表示字串大小比較,以acill碼位置作為比較。不直接支援<>運算子,還有邏輯運算子 || 和 && 它需要用-a[and] o[or]表示。

剛才使用的[],現在再來看使用[[]]

案例:

使用命令:[[ 2 < 3 ]]&&echo OK

輸出OK.

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

輸出:ok

注意:[[]] 運算子只是[]運算子的擴充。能夠支援<,>符號運算不需要轉義符,它還是以字串比較大小。裡面支援邏輯運算子 || 和 && 

bash 的條件表示式中有三個幾乎等效的符號和命令:test[][[]]。通常,大家習慣用if [];then這樣的形式。而[[]]的出現,根據ABS所說,是為了相容><之類的運算子。
不考慮對低版本bash和對sh的相容的情況下,用[[]]是相容性強,而且效能比較快,在做條件運算時候,可以使用該運算子。