20170824 Shell編程進階(一)

  • 選擇執(zhí)行:if語句
  • 條件判斷:case語句
  • 循環(huán)控制:for語句
  • 循環(huán)控制:while語句和until語句
  • 循環(huán)控制:continue, break, shift語句
  • 循環(huán)控制:select語句
  • 信號捕捉:trap語句

一、選擇執(zhí)行:if 語句

  • 單分支
if 判斷條件; then
      判斷條件為真的代碼
fi
  • 雙分支
if 判斷條件; then
      判斷條件為真的代碼
else
      判斷條件為假的代碼
fi
  • 多分支:逐條件判斷,直到滿足條件執(zhí)行分支代碼,忽略之后的條件判斷
if 判斷條件1; then 
      判斷條件1為真的代碼 
elif 判斷條件2; then
      判斷條件2為真的代碼
elif 判斷條件3; then
      判斷條件3為真的代碼
... 
else 
      上述所有條件為假的代碼
fi
  • 實驗:當(dāng)運行腳本時已經(jīng)自帶參數(shù),輸出參數(shù)值;若運行腳本時沒有自帶參數(shù),則提示輸入?yún)?shù),并輸出參數(shù)值
#! /bin/bash
if [ $# -eq 0 ] ;then
        read -p "please type the words: " words
else
        words=$*
fi
echo $words

二、條件判斷:case 語句

  • 語法:
case 變量引用 in 
PAT1)
        分支語句1
        ;;
PAT2)
        分支語句2
        ;;
PAT3)
        分支語句3
        ;;
...
*)
        默認(rèn)分支語句
        ;;
esac

  • PAT:支持glob通配符
    *:任意長度任意字符
    ?:任意單個字符
    []:指定范圍內(nèi)的任意單個字符
    a|b:a或b

  • 實現(xiàn)一個菜單:

序號 菜名 價格
1 lamian 10
2 huimian 10
3 yangroutang 20
4 gaifan 15
5 jiaozi 20

要求輸入菜名序號后,顯示出相應(yīng)菜品的價格

#! /bin/bash
cat <<eof
menu:
1) lamian
2) huimian
3) yangroutang
4) gaifan
5) jiaozi
eof
read -p "choose your menu(eg:1): " menu
case $menu in
1|2)
        echo "menu $menu price is 10"
        ;;  
3|5)
        echo "menu $menu price is 20"
        ;;  
4)
        echo "menu $menu price is 15"
        ;;  
*)
        echo "wrong menu"
        ;;  
esac

三、循環(huán)控制:for 語句

  • 循環(huán)結(jié)構(gòu)的基本組成:初始值、循環(huán)開始和結(jié)束條件、循環(huán)體
(1)基本用法:
  • 語法:
for 變量名 in 列表; do
循環(huán)體
done
  • 執(zhí)行機制:
    依次將列表中的元素賦值給“變量名”; 每次賦值后即執(zhí)行一次循環(huán)體; 直到列表中的元素耗盡,循環(huán)結(jié)束

  • 列表生成方式:

    • 直接給出列表
    • 整數(shù)列表: {start..end}, {start..end...step}
    • 返回列表的命令:$(COMMAND) 或 `COMMAND`,如 $(seq start step end)
    • 使用glob:*.sh
    • 變量引用:$@, $*
(2)特殊用法(雙小括號方法):
  • 雙小括號法:用兩組括號嵌套(()),可以實現(xiàn)C語言風(fēng)格變量操作,如
    let i++等同于((i++))

  • for 循環(huán)的特殊格式

    • 語法:
for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式)); do
      循環(huán)體
done
  • 控制變量初始化:僅當(dāng)運行到循環(huán)代碼段開始時執(zhí)行一次

  • 控制變量的修正表達式:每輪循環(huán)結(jié)束會先進行控制變量修正運算,而后再做條件判斷

  • 實驗:建立一個10*10矩陣,每個位置以“行號.列號”方式命名,如第1行第3列的內(nèi)容為1.3

#! /bin/bash
for i in {1..10}; do  
        for j in {1..10}; do
                echo -ne "$i.$j\t"
        done
        echo
done

***另一種實現(xiàn)***

#! /bin/bash
for ((i=1;i<=10;i++));do 
        for ((j=1;j<=10;j++));do
                echo -ne "$i.$j\t"
        done
        echo
done

四、循環(huán)控制:while 語句和until 語句

(1)while 語句
  • 語法:
while CONDITON ; do
      循環(huán)體
done
  • CONDITION 循環(huán)控制條件
    值為true或false,只有為true時才能執(zhí)行循環(huán)體,一般在循環(huán)體中有循環(huán)控制變量在每一次循環(huán)中變化,最終使CONDITION值由true轉(zhuǎn)變?yōu)閒alse,從而終止循環(huán)

  • 進入條件:CONDITION=true
    退出條件:CONDITION=false

  • 無限循環(huán):

while true; do
      COMMANDs
done
  • 特殊用法:遍歷文件的每一行
while read line ; do
      循環(huán)體 
done < /path/to/file     //依次讀取/path/to/file文件的每一行,并將行復(fù)制給變量line
  • 實驗:判斷/etc/passwd文件每個用戶是系統(tǒng)用戶還是普通用戶(CentOS 7)
#! /bin/bash
while read userline; do
        userid=`echo $userline | cut -d: -f3`
        username=`echo $userline | cut -d: -f1`
        if (( userid < 1000 )); then
                echo "$username is system user"
        else
                echo "$username is common user"
        fi  
done < /etc/passwd
(2)until 語句
  • 語法:
until CONDITION ; do
      循環(huán)體
done
  • CONDITION循環(huán)控制條件
    值為false時執(zhí)行循環(huán)體,當(dāng)值為true時,終止循環(huán)

  • 進入條件:CONDITION=false
    退出條件:CONDITION=true

  • 無限循環(huán):

until false; do
      COMMANDs
done

五、循環(huán)控制:continue, break, shift語句

(1)continue 語句
  • continue [N]:提前結(jié)束第N層的本輪循環(huán),而直接進入下一輪判斷
    最內(nèi)層為第1層

  • 不寫層數(shù)默認(rèn)為第1層

  • 在循環(huán)體中使用,語法:

while CONDITION1; do
      CMD1
      ...
      if CONDITION2; then
            continue     //continue命令表示跳出本輪循環(huán),直接下一輪循環(huán)開始判斷CONDITION1值
      fi
      CMDn
      ...
done
  • 實驗:輸出與上文類似的10*10矩陣,但是行號與列號相同的位置為空白
#! /bin/bash
for i in {1..10}; do  
        for j in {1..10}; do
                [ $j -eq $i ] && { echo -ne "\t";continue; }     //行號與列號相同時,輸出制表符,跳出本輪循環(huán)
                echo -ne "$i.$j\t"
        done
        echo
done
(2)break 語句
  • break [N]:提前結(jié)束第N層循環(huán)
    最內(nèi)層為第1層

  • 不寫層數(shù)默認(rèn)為第1層

  • 在循環(huán)體中使用,語法:

while CONDITION1; do
      CMD1
      ...
      if CONDITION2; then
            break     //continue命令表示跳出本層循環(huán),執(zhí)行本層循環(huán)外的語句
      fi
      CMDn
      ...
done
  • 實驗:輸出與上文類似的10*10矩陣,但是列號大于等于行號的位置為空白
#! /bin/bash
for i in {1..10}; do  
        for j in {1..10}; do
                [ $j -eq $i ] && break     //行號與列號相同時,終止本層循環(huán),故列號大于行號的位置也沒有機會輸出
                echo -ne "$i.$j\t"
        done
        echo
done
(3)shift 語句
  • 語法:shift [N]

  • 用于將參數(shù)列表左移N次,缺省為左移一次

  • 參數(shù)列表一旦被移動,最左端的那個參數(shù)就從列表中刪除

  • while 循環(huán)遍歷位置參量列表時,常用到shift

  • 實驗:
    (1)輸入n個參數(shù),第1行輸出第1-n個參數(shù),第2行輸出第2-n個參數(shù),以此類推,直到第n行輸出第n個參數(shù)

#! /bin/bash
while [ $# -gt 0 ]; do
        echo "$*"
        shift
done

(2)輸入n個參數(shù),每行輸出一個參數(shù)

#! /bin/bash
until [ -z "$1" ];do
        echo "$1"
        shift
done

六、循環(huán)控制:select 語句

  • 語法:
select variable in list; do
      循環(huán)體命令
done
  • select 循環(huán)主要用于創(chuàng)建菜單,按數(shù)字順序排列的菜單項將顯示在標(biāo)準(zhǔn)錯誤上,并顯示PS3 提示符,等待用戶輸入

  • 用戶輸入菜單列表中的某個數(shù)字,執(zhí)行相應(yīng)的命令

  • 用戶輸入被保存在內(nèi)置變量REPLY 中

  • select是個無限循環(huán),因此要記住用break命令退出循環(huán),或用exit命令終止腳本,也可以按ctrl+c退出循環(huán)

  • select經(jīng)常和case聯(lián)合使用

  • 實驗:實現(xiàn)一個菜單,輸入菜單編號顯示價格,不存在的菜單號顯示"wrong menu"并退出

序號 菜名 價格
1 lamian 10
2 huimian 10
3 yangroutang 20
4 gaifan 15
5 jiaozi 20
#! /bin/bash
PS3="please type the menu num: "          //環(huán)境變量PS3指定提示符格式
select menu in lamian huimian rangroutang gaifan jiaozi; do
        case $REPLY in          //用戶的輸入自動存入REPLY變量中
        1)  
                echo "the price of lamian is \$10"
                ;;  
        2)  
                echo "the price of huimian is \$10"
                ;;  
        3)  
                echo "the price of rangroutang is \$20"
                ;;  
        4)  
                echo "the price of gaifan is \$15"
                ;;  
        5)  
                echo "the price of jiaozi is \$20"
                ;;  
        *)  
                echo "wrong menu"
                break          //select語句默認(rèn)無限循環(huán),需要有break命令退出循環(huán)
                ;;  
        esac
done

七、信號捕捉:trap 語句

  • trap '觸發(fā)指令' 信號
    進程收到系統(tǒng)發(fā)出的信號后,執(zhí)行觸發(fā)指令,而不執(zhí)行信號操作

  • trap ' ' 信號
    進程收到系統(tǒng)發(fā)出的信號后,直接忽略

  • trap '-' 信號
    進程收到系統(tǒng)發(fā)出的信號后,恢復(fù)信號操作

*trap -p
列出自定義信號操作

  • 實驗:trap語句驗證,以信號2 SIGINT為例
#! /bin/bash
trap 'echo "signal:sigint"' sigint     //接到sigint信號輸出"signal:sigint"
trap -p
for (( i=1;i<=5;i++ )); do
        echo $i
        sleep 2
done
trap ' ' sigint                        //接到sigint信號直接忽略
trap -p
for (( j=6;j<=10;j++ )); do
        echo $j
        sleep 2
done
trap '-' sigint                        //接到sigint信號恢復(fù)信號操作
trap -p
for (( k=11;k<=15;k++ )); do
        echo $k
        sleep 2
done

共3個循環(huán),每個循環(huán)開始前都輸出了相應(yīng)的自定義信號情況
輸出1-5時,Ctrl+C發(fā)出sigint信號后,直接執(zhí)行替換的命令echo "signal:sigint,循環(huán)繼續(xù)
輸出6-10時,Ctrl+C發(fā)出sigint信號后,直接忽略信號,循環(huán)繼續(xù)
輸出11-15時,Ctrl+C發(fā)出sigint信號后,恢復(fù)信號本身作用,循環(huán)被終止

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容