天天看點

Unix系列shell程式編寫3

3>在Shell中使用資料變量  使用者可以在Shell中使用資料變量,例如ba.sh程式:

    cd/usr/icewalk

    ls|cpio -o > /dev/fd0

  該程式中要備份的目錄為一常量,即該程式隻能用來備份一個目錄。若在該程式中使用變量,則會使其更通用:

    workdir=$1

    cd $workdir

    ls * |cpio -o > /dev/fd0

  通過這一改變,使用者可以使用程式備份變量$workdir指定的目錄。例如我們要備份/home/www的内容,隻要運作ba.sh /home/www即可實作。(若不明白 $1,下面将詳細介紹shell參數的傳遞,$1代表本sh程式-ba.sh的第一個參數)

  4>在Shell程式中加上注釋

  為了增加程式的可讀性,我們提倡加入注釋。在Shell程式中注釋将以"#"号開始。當Shell解釋到"#"時,會認為從"#"号起一直到該行行尾為注釋。

  5>對Shell變量進行算術運算

  進階語言中變量是具有類型的,即變量将被限制為某一資料類型,如整數或字元類型。Shell變量通常按字元進行存儲,為了對Shell變量進行算術運算,必須使用expr指令。

  expr指令将把一個算術表達式作為參數,通常形式如下:

    expr [數字] [操作符] [數字]

  由于Shell是按字元形式存儲變量的,是以使用者必須保證參加算術運算的操作數必須為數值。下面是有效的算術操作符:

    +   兩個整數相加

    -   第一個數減去第二個數

    *   兩整數相乘

    /   第一個整數除以第二個整數

    %   兩整數相除,取餘數

  例如:

    $expr 2 + 1

     結果顯示:3

    $expr 5 - 3

     結果顯示:2若expr的一個參數是變量,那麼在表達式計算之前用變量值替換變量名。

    $int=3

    $expr $int + 4

    結果顯示:7

  使用者不能單純使用"*"做乘法,若輸入:

    $expr 4*5

  系統将會報錯,因為Shell看到"*"将會首先進行檔案名替換。正确形式為:

    $expr 4 /* 5

     結果顯示:20

  多個算術表達式可以組合在一起,例如:

    $expr 5 + 7 / 3

    結果顯示:7

  運算次序是先乘除後加減,若要改變運算次序,必須使用"`"号,如:

    $int=`expr 5 + 7`

    $expr $int/3

     結果顯示:4

    或者:

    $expr `expr 5+7`/3

    結果顯示:4

  6>向Shell程式傳遞參數

  一個程式可以使用兩種方法獲得輸入資料。一是執行時使用參數。另一種方法是互動式地獲得資料。vi編輯程式可以通過互動式的方法獲得資料,而ls和expr則從參數中取得資料。以上兩種方法Shell程式都可以使用。在"互動式讀入資料"一節中将介紹Shell程式通過互動式的方法獲得參數。

  通過指令行給Shell程式傳遞參數可以擴大程式的用途。以前面提到的ba.sh程式為例:

  $cat >re.sh

  cd $workdir

  cpio -i < /dev/fd0

  ^d

  程式re.sh恢複了ba.sh程式備份的所有檔案。若隻從軟碟上恢複一個指定的檔案,可以用該檔案名作為參數,傳遞給Shell程式re.sh:

  程式改寫如下:

  $cat >re2.sh

  cd $workdir

  cpio -i $1 < /dev/fd0

  ^d

  使用者可以指定要恢複的檔案,例如fname

  $re2.sh fname

此時檔案fname作為第一個位置參數傳遞給re2.sh,re2.sh的缺點是要恢複兩個或多個檔案要重複運作,我們可以用$*變量傳遞不确定的參數給程式:

  $cat >re3.sh

  cd $workdir

  cpio -i $* < /dev/fd0

  ^d

  我們就可以恢複多個檔案,例如fname1,fname2,fname3

  $re3.sh fname1 fname2 fname3

  (以上程式re.sh,re2.sh,re3.sh,假設使用者已經chmod了可執行權利)

  因為沒有指派的變量可以作為NULL看待,是以若是程式re3.sh在執行時候沒賦予參數,那麼一個空值将被插入到cpio指令中。該指令将恢複所有儲存的檔案。

條件判斷語句

  條件判斷語句是程式設計語言中十分重要的語句,該語句的含義是當某一條件滿足時,執行指定的一組指令。

1>if - then語句

  格式: if command1

     then

       command2

       command3

     fi      ---(if 語句結束)

       command4

  每個程式或指令執行結束後都有一個傳回的狀态,使用者可以用Shell變量$?獲得這一狀态。if語句檢查前面指令執行的傳回狀态,若該指令成功執行,那麼在then和fi之間的指令都将被執行。在上面的指令序列中,command1和command4總要執行。若command1成功執行,command2和command3也将執行。

  請看下面程式:

    #unload -program to backup and remove files

    cd $1

    ls -a | cpio -o > /dev/mnt0

    rm *

  該程式在備份資料後,删除檔案,但當cpio指令不能成功執行時,rm指令還是把資料删除了,我們可不希望這樣,為了避免此情況,可以用if - then語句:

    #--解除安裝和判斷删除程式

    cd $1

    if ls -a | cpio > /dev/mnt0

    then

      rm *

    fi

  上面程式在cpio執行成功後才删除檔案

同時,若執行沒有成功,我們希望得到提示,sh中的echo指令可以向使用者顯示消息,并顯示後換行,上面程式可以寫成:

     #--解除安裝和判斷删除程式

    cd $1

    if ls -a | cpio > /dev/mnt0

    then

      echo "正删除檔案資料... ..."

      rm *

    fi

  echo指令可以使用一些特殊的逃逸字元進行格式化輸出,下面是這些字元及其含義:

    /b  Backspace

    /c  顯示後不換行

    /f  在終端上螢幕的開始處顯示

    /n  換行

    /r  回車

    /t  制表符

    /v  垂直制表符

    /   反斜框

    /0nnn 用1,2或3位8進制整數表示一個ASCII碼字元

2>if - then - else語句

  不用多說它的作用,别的進階語言中都有,格式為:

  if command1

  then

    command2

    command3

  else

    command4

    command5

  fi

  在此結構中,command1中是先執行,當command1成功執行時,将執行command2和command3,否則執行command4和command5

  注意看下面程式:

    #備份程式

    cd $1

    if ls -a |cpio -o > /dev/mnt0

    then

      echo "删除源資料... ..."

      rm *

    else

      echo "錄音帶備份失敗!"

    fi

3>test指令進行條件測試

  if語句可以通過測試指令執行的傳回狀态來控制指令的執行,若要測試其他條件,在bsh中可以使用test指令。該指令檢測某一條件,當條件為真時傳回0,否則傳回非0值。test指令可以使Shell程式中的if語句象其他程式語言中的條件判斷語句一樣,具有很強的功能。

  test指令的使用方法為:

    test condition

  可測試的條件分為4類:

  1)測試兩個字元串之間的關系。

  2)測試兩個整數之間關系。

  3)測試檔案是否存在或是否具有某種狀态或屬性。

  4)測試多個條件的與(and)或(or)組合。

1、條件語句>>test語句

1>測試字元串間的關系

  bsh把所有的指令行和變量都看作字元串。一些指令如expr和test可以把字元當作數字進行操作。

  同樣任何數字也可以作為字元串進行操作。

  使用者可以比較兩個字元串相等或不等,也可以測試一個串是否賦了值。有關串的操作符如下:

    str1 = str2      當兩個串有相同内容、長度時為真

    str1 != str2      當串str1和str2不等時為真

    -n str1         當串的長度大于0時為真(串非空)

    -z str1         當串的長度為0時為真(空串)

    str1           當串str1為非空時為真

  不但Shell程式可以使用test進行條件判斷,test指令也可以獨立執行,如:

    $str1=abcd

    $test $str1 = abcd

    $echo $?

    結果顯示:0

與上例中第一行指派語句中的等号不同,test指令中的等号兩邊必須要有空格。本例test指令共有3個參數。注意兩個串相等必須是長度和内容都相等。

    $str1="abcd "

    $test "$str1" = abcd

    $echo $?

    結果顯示:1

  上面str1包含5個字元,其中最後一個為空格符。而test指令中的另一個串隻有4個字元,是以兩串不等,test傳回1。

  不帶任何操作符和使用-n操作符測試一個串結果是一樣的,例如:

    $str1=abce

    $test $str1

    $echo $?

    結果顯示:0    

    $test -n $str1

    $echo $?

    結果顯示:0

  但是,上面兩條指令也有一點差别,反映出了使用test指令潛在的問題,請看下例:

    $str1="   "

    $test $str1

    $echo $?

    結果顯示:1

    $test -n "$str1"

    $echo $?

    結果顯示:0

    $test -n $str1

    結果顯示:test:argument expected

  上例中,第一次測試為假因為Shell在執行指令行之前首先要進行變量替換,即把$str1換成空格,然後shell又将指令行上的空格删除,故test指令測試到的為空串。而在第二次測試中,變量替換後空格位于括号内,故不會被删除,test測試到的是一個包含空格的串,在第三次測試中,shell把空格删除,隻把-n傳個test指令,是以顯示參數錯。

2>測試兩個整數之間關系

  test指令與expr指令一樣,也可以把字元轉變成整數,然後對其操作。test指令對兩個數進行比較,使用的操作符如下:

    int1 -eq int2    兩數相等為真

    int1 -ne int2    兩數不等為真

    int1 -gt int2    int1大于int2為真

    int1 -ge int2    int1大于等于int2為真

    int1 -lt int2    int1小于int2為真

    int1 -le int2    int1小于等于int2為真

  下面的例子反映了字元串比較與數字比較的不同:

    $str1=1234

    $str2=01234

    $test $str1 = $str2

    $echo $?

    結果顯示:1

    $test $str1 -eq $str2

    $echo $?

    結果顯示:0

3>有關檔案的測試

  使用test進行的第三類測試是測試檔案的狀态,使用者可以測試檔案是否存在,是否可寫以及其他檔案屬性。下面是檔案測試時使用的選項。注意隻有檔案存在時,才有可能為真。

  -r file     使用者可讀為真

  -w file     使用者可寫為真

  -x file     使用者可執行為真

  -f file     檔案為正規檔案為真

  -d file     檔案為目錄為真

  -c file     檔案為字元特殊檔案為真

  -b file     檔案為塊特殊檔案為真

  -s file     檔案大小非0時為真

  -t file     當檔案描述符(預設為1)指定的裝置為終端時為真