1. 程式人生 > >03: 迴圈結構 case語句 、 函式及中斷控制 總結和答疑

03: 迴圈結構 case語句 、 函式及中斷控制 總結和答疑

Top

NSD SHELL DAY03

  1. 案例1:使用for迴圈結構
  2. 案例2:使用while迴圈結構
  3. 案例3:基於case分支編寫指令碼
  4. 案例4:使用Shell函式
  5. 案例5:中斷及退出

1 案例1:使用for迴圈結構

1.1 問題

本案例要求編寫一個Shell指令碼chkhosts.sh,利用for迴圈來檢測多個主機的存活狀態,相關要求及說明如下:

  • 對192.168.4.0/24網段執行ping檢測
  • 指令碼能遍歷ping各主機,並反饋存活狀態

執行檢測指令碼以後,反饋結果如圖-1所示。

圖-1

1.2 方案

在Shell指令碼應用中,常見的for迴圈採用遍歷式、列表式的執行流程,通過指定變數從值列表中迴圈賦值,每次複製後執行固定的一組操作。

for迴圈的語法結構如下所示:

 
  1. for 變數名 in 值列表
  2. do
  3. 命令序列
  4. done
  5.  
  6. for 變數名 in {1..5}
  7. do
  8. 命令序列
  9. done
  10. for 變數名 in `seq 5`
  11. do
  12. 命令序列
  13. done
  14.  
  15. for 變數名 in `ls /etc/*.conf`
  16. do
  17. 命令序列
  18. done

1.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:練習for迴圈基本用法

指令碼1,通過迴圈批量顯示5個hello world:

 
  1. [[email protected] ~]# vim for01.sh
  2. #!/bin/bash
  3. for i in 1 2 3 4 5
  4. do
  5.         echo "hello world"
  6. done
  7. [[email protected] ~]# chmod +x for01.sh
  8. [
    [email protected]
    ~]# ./for01.sh

指令碼2,通過迴圈批量顯示10個hello world:

 
  1. [[email protected] ~]# vim for02.sh
  2. #!/bin/bash
  3. for i in {1..10}
  4. do
  5.         echo "hello world"
  6. done
  7. [[email protected] ~]# chmod +x for02.sh
  8. [[email protected] ~]# ./for02.sh

指令碼3,通過迴圈批量顯示10個數字:

 
  1. [[email protected] ~]# vim for03.sh
  2. #!/bin/bash
  3. for i in {1..10}
  4. do
  5.         echo "$i"
  6. done
  7. [[email protected] ~]# chmod +x for03.sh
  8. [[email protected] ~]# ./for03.sh

步驟二:批量檢測多個主機的存活狀態

1)編寫指令碼如下:

命令備註:ping命令可以測試某臺主機的連通性,

使用-c選項可以設定ping的次數,

使用-i選項可以設定多次ping之間的間隔時間(單位秒),

使用-W選項可以設定ping不通時的超時時間(單位秒)。

 
  1. [[email protected] ~]# vim chkhosts.sh
  2. #!/bin/bash
  3. for i in {1..254}
  4. do
  5. ping -c 3 -i 0.2 -W 1 192.168.4.$i &> /dev/null
  6. if [ $? -eq 0 ] ; then
  7. echo "Host 192.168.4.$i is up."
  8. else
  9. echo "Host 192.168.4.$i is down."
  10. fi
  11. done
  12. [[email protected] ~]# chmod +x chkhosts.sh

4)測試、驗證指令碼

 
  1. … …
  2. [[email protected] ~]# ./chkhosts.sh
  3. Host 192.168.4.5 is up.
  4. Host 192.168.4.6 is down
  5. … …

步驟三:建立賬戶的案例

建立users.txt,寫入無規律的賬戶名稱,最後使用for迴圈讀取該檔案,批量建立賬戶並設定密碼。

 
  1. [[email protected] ~]# vim addfor.sh
  2. #!/bin/bash
  3. for i in `cat /root/user.txt`
  4. do
  5. useradd $i
  6. echo 123456 | passwd --stdin $i
  7. done

附加擴充套件知識(C語言風格的for迴圈語法格式)

 
  1. [[email protected] ~]# vim cfor.sh
  2. #!/bin/bash
  3. for ((i=1;i<=5;i++))
  4. do
  5. echo $i
  6. done

2 案例2:使用while迴圈結構

2.1 問題

本案例要求編寫2個使用while迴圈的指令碼程式,分別實現以下目標:

  • 提示使用者猜測一個隨機數,直到才對為止
  • 檢測192.168.4.0/24網段,列出不線上的主機地址

2.2 方案

while迴圈屬於條件式的執行流程,會反覆判斷指定的測試條件,只要條件成立即執行固定的一組操作,直到條件變化為不成立為止。所以while迴圈的條件一般通過變數來進行控制,在迴圈體內對變數值做相應改變,以便在適當的時候退出,避免陷入死迴圈。

while迴圈的語法結構如下所示:

 
  1. while 條件測試
  2. do
  3. 命令序列
  4. done
  5.  
  6.  
  7. while :
  8. do
  9. 命令序列
  10. done

2.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:練習while迴圈基本用法

指令碼1,無心的死迴圈指令碼:

 
  1. [[email protected] ~]# vim while01.sh
  2. #!/bin/bash
  3. i=1
  4. while [ $i -le 5 ]
  5. do
  6.         echo "$i"
  7. done
  8. [[email protected] ~]# chmod +x while01.sh
  9. [[email protected] ~]# ./while01.sh                //死迴圈,需要使用Ctrl+C終止指令碼

指令碼2,有效迴圈指令碼:

 
  1. [[email protected] ~]# vim while02.sh
  2. #!/bin/bash
  3. i=1
  4. while [ $i -le 5 ]
  5. do
  6.         echo "$i"
  7.         let i++
  8. done
  9. [[email protected] ~]# chmod +x while02.sh
  10. [[email protected] ~]# ./while02.sh

指令碼3,死迴圈的一般格式:

 
  1. [[email protected] ~]# vim while03.sh
  2. #!/bin/bash
  3. while :
  4. do
  5.         echo "hello world"
  6. done
  7. [[email protected] ~]# chmod +x while03.sh
  8. [[email protected] ~]# ./while03.sh                //死迴圈,需要使用Ctrl+C終止指令碼

步驟二:提示使用者猜測一個隨機數,直到才對為止

使用系統自帶變數RANDOM提取隨機數(1-100),使用while :製作死迴圈。

指令碼編寫參考如下:

 
  1. [[email protected] ~]# vim guess.sh
  2. #!/bin/bash
  3. num=$[RANDOM%100+1]
  4. i=0
  5. while :
  6. do
  7. read -p "隨機數1-100,你猜:" guess
  8. let i++                                    //猜一次,計數器加1,統計猜的次數
  9. if [ $guess -eq $num ];then
  10. echo "恭喜,猜對了"
  11. echo "你猜了$i次"
  12. exit
  13. elif [ $guess -gt $num ];then
  14. echo "猜大了"
  15. else
  16. echo "猜小了"
  17. fi
  18. [[email protected] ~]# chmod +x guess.sh

執行指令碼並驗證結果:

 
  1. [[email protected] ~]# ./guess.sh

步驟三:檢測192.168.4.0/24網段,列出不線上的主機地址

1)任務需求及思路分析

要求的是“檢測192.168.4.0/24網段,列出不線上的主機地址”。

檢測目標是一個網段,其網路部分“192.168.4.”可以作為固定的字首;而主機部分包括從1~254連續的地址,所以可結合while迴圈和自增變數進行控制。

2)根據實現思路編寫指令碼

 
  1. [[email protected] ~]# vim chknet.sh
  2. #!/bin/bash
  3. i=1
  4. while [ $i -le 254 ]
  5. do
  6. IP="192.168.4.$i"
  7. ping -c 3 -i 0.2 -W 1 $IP &> /dev/null
  8. if [ $? -eq 0 ] ; then
  9. echo "Host $IP is up."
  10. else
  11. echo "Host $IP is down."
  12. fi
  13. let i++
  14. done
  15. [[email protected] ~]# chmod +x chknet.sh

3)測試、驗證指令碼

 
  1. [[email protected] ~]# ./chknet.sh
  2. Host 192.168.4.1 is down.
  3. Host 192.168.4.2 is down.
  4. Host 192.168.4.3 is down.
  5. Host 192.168.4.4 is down.
  6. Host 192.168.4.5 is up.
  7. .. ..
  8. Host 192.168.4.250 is down.
  9. Host 192.168.4.251 is down.
  10. Host 192.168.4.252 is down.
  11. Host 192.168.4.253 is down.
  12. Host 192.168.4.254 is down.

3 案例3:基於case分支編寫指令碼

3.1 問題

本案例要求編寫test.sh指令碼,相關要求如下:

  • 能使用redhat、fedora控制引數
  • 控制引數通過位置變數$1傳入
  • 當用戶輸入redhat引數,指令碼返回fedora
  • 當用戶輸入fedora引數,指令碼返回redhat
  • 當用戶輸入其他引數,則提示錯誤資訊

3.2 方案

case分支屬於匹配執行的方式,它針對指定的變數預先設定一個可能的取值,判斷該變數的實際取值是否與預設的某一個值相匹配,如果匹配上了,就執行相應的一組操作,如果沒有任何值能夠匹配,就執行預先設定的預設操作。

case分支的語法結構如下所示:

 
  1. case 變數 in
  2. 模式1)
  3. 命令序列1 ;;
  4. 模式2)
  5. 命令序列2 ;;
  6. .. ..
  7. *)
  8. 預設命令序列
  9. esac

3.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:編寫指令碼檔案

指令碼編寫參考如下:

 
  1. [[email protected] ~]# vim test.sh
  2. #!/bin/bash
  3. case $1 in
  4. redhat)
  5.         echo "fedora";;
  6. fedora)
  7.         echo "redhat";;
  8.     *)                                             //預設輸出指令碼用法
  9. echo "用法: $0 {redhat|fedora}"
  10. esac
  11.  
  12. [[email protected] ~]# chmod +x test.sh

步驟三:驗證、測試指令碼

未提供引數,或提供的引數無法識別時,提示正確用法:

 
  1. [[email protected] ~]# ./test.sh
  2. 用法: ./test.sh {redhat|fedora}

確認指令碼可以響應redhat控制引數:

 
  1. [[email protected] ~]# ./test.sh redhat
  2. fedora

確認指令碼可以響應fedora控制引數:

 
  1. [[email protected] ~]# ./test.sh fedora
  2. redhat

4 案例4:使用Shell函式

4.1 問題

本案例要求編寫指令碼mycolor.sh,相關要求如下:

  • 將顏色輸出的功能定義為函式
  • 呼叫函式,可以自定義輸出內容和顏色

4.2 方案

在Shell指令碼中,將一些需重複使用的操作,定義為公共的語句塊,即可稱為函式。通過使用函式,可以使指令碼程式碼更加簡潔,增強易讀性,提高Shell指令碼的執行效率

1)函式的定義方法

格式1:

 
  1. function 函式名 {
  2. 命令序列
  3. .. ..
  4. }

格式2:

 
  1. 函式名() {
  2. 命令序列
  3. .. ..
  4. }

2)函式的呼叫

直接使用“函式名”的形式呼叫,如果該函式能夠處理位置引數,則可以使用“函式名 引數1 引數2 .. ..”的形式呼叫。

注意:函式的定義語句必須出現在呼叫之前,否則無法執行。

3) 測試語法格式

 
  1. [[email protected] ~]# mycd(){                        //定義函式
  2. > mkdir /test
  3. > cd /test
  4. > }
  5. [[email protected] ~]# mycd                            //呼叫函式
  6.  
  7. [[email protected] ~]# mycd(){                        //定義函式
  8. > mkdir $1
  9. > cd $1
  10. > }
  11. [[email protected] ~]# mycd /abc                            //呼叫函式
  12. [[email protected] ~]# mycd /360                            //呼叫函式

4.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:編寫mycolor.sh指令碼

1)任務需求及思路分析

使用者在執行時提供2個整數引數,這個可以通過位置變數$1、$2讀入。

呼叫函式時,將使用者提供的兩個引數傳遞給函式處理。

顏色輸出的命令:echo -e "\033[32mOK\033[0m"。

3X為字型顏色,4X為背景顏色。

2)根據實現思路編寫指令碼檔案

 
  1. [[email protected] ~]# vim mycolor.sh
  2. #!/bin/bash
  3. cecho() {
  4. echo -e "\033[$1m$2\033[0m"
  5. }
  6. cecho 32 OK
  7. cecho 33 OK
  8. cecho 34 OK
  9. cecho 35 OK
  10.  
  11. [[email protected] ~]# chmod +x mycolor.sh

3)測試指令碼執行效果

 
  1. [[email protected] ~]# ./mycolor.sh

使用函式,優化改進前面的指令碼:

 
  1. [[email protected] ~]# vim myping.sh
  2. #!/bin/bash
  3. myping(){
  4. ping -c1 -W1 $1 &>/dev/null
  5. if [ $? -eq 0 ];then
  6. echo "$1 is up"
  7. else
  8. echo "$1 is down"
  9. fi
  10. }
  11. for i in {1..254}
  12. do
  13. myping 192.168.4.$i &
  14. done
  15. wait
  16. #wait命令的作用是等待所有後臺程序都結束才結束指令碼。

Shell版本的fork炸彈

 
  1. [[email protected] ~]# vim test.sh
  2. #!/bin/bash
  3. .(){
  4. .|.&
  5. }
  6. .

5 案例5:中斷及退出

5.1 問題

本案例要求編寫兩個Shell指令碼,相關要求如下:

  • 從鍵盤迴圈取整數(0結束)並求和,輸出最終結果
  • 找出1~20以內6的倍數,並輸出她的平方值

5.2 方案

通過break、continue、exit在Shell指令碼中實現中斷與退出的功能。

break可以結束整個迴圈;continue結束本次迴圈,進入下一次迴圈;exit結束整個指令碼,案例如下:

 
  1. [[email protected] ~]# vim test.sh
  2. #!/bin/bash
  3. for i in {1..5}
  4. do
  5.      [ $i -eq 3 ]&& break //這裡將break替換為continue,exit分別測試指令碼執行效果     echo $i
  6. done
  7. echo "Game Over"

5.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:編寫求和指令碼sum.sh

1)編寫指令碼檔案

 
  1. [[email protected] ~]# vim sum.sh
  2. #!/bin/bash
  3. SUM=0
  4. while :
  5. do
  6. read -p "請輸入整數(0表示結束):" x
  7. [ $x -eq 0 ] && break
  8. SUM=$[SUM+x]
  9. done
  10. echo "總和是:$SUM"
  11.  
  12. [[email protected] ~]# chmod +x sum.sh
  13. [[email protected] ~]# ./sum.sh

步驟二:編寫指令碼檔案,找出1-20內6的倍數,並列印她的平方值

1)編寫指令碼檔案

注意:要求列印所有6的倍數的平方值,也就是非6的倍數都跳過!!!

 
  1. [[email protected] ~]# vim test.sh
  2. #!/bin/bash
  3. for i in {1..20}
  4. do
  5. [ $[i%6] -ne 0 ] && continue
  6. echo $[i*i]
  7. done
  8.  
  9. [[email protected] ~]# chmod +x test.sh
  10. [[email protected] ~]# ./test.sh