Shell腳本之條件選擇與循環

前言

Bash語言是過程式編程語言,這篇文章主要講到:條件選擇、循環,這兩種用法。
條件選擇語句主要用到的有if,case這兩種判斷語句。
Shell中有3種循環,分別是for,while,until,until與while正好相反,前者條件爲假則執行,後者條件爲真時執行。

條件選擇


if條件判斷

單分支條件判斷:

if 判斷條件;then 
        條件爲真的分支代碼 
fi 

雙分支條件判斷:

if 判斷條件; then 
    條件爲真的分支代碼 
else 
    條件爲假的分支代碼 
fi

多分支條件判斷:

if 判斷條件1; then 
    條件爲真的分支代碼 
elif 判斷條件2; then 
    條件爲真的分支代碼 
elif 判斷條件3; then 
    條件爲真的分支代碼 
else 
    以上條件都爲假的分支代碼 
fi

注:逐條件進行判斷,第一次遇爲“真”條件時,執行其分支, 而後結束整個if語句

下面用if條件判斷語句寫一個腳本來深入的理解:

#!/bin/bash
#
if ping -c1 -W2 station1 &> /dev/null; then 
    echo 'Station1 is UP' 
elif grep "station1" ~/maintenance.txt &> /dev/null 
then 
    echo 'Station1 is undergoing maintenance' 
else 
    echo 'Station1 is unexpectedly DOWN!' 
    exit 1 
fi

注:這個腳本,第一步是先判斷station1是否能ping通,如果ping通了就在屏幕上打印Station1是UP狀態。判斷結束。
如果不能ping通就跳到下一個判斷,查詢~/maintenance.txt裏面有沒有station1,如果能查詢到,則在屏幕上打印
station1 是在維護狀態,半段結束。如果依然不能在在~/maintenance.txt裏面查詢到station1,則跳到下一步,以上
的判斷都不爲真,則打印station1是DOWN狀態,並退出返回狀態數1.


case語句

case 變量引用 in 
PAT1) 
    分支1 
    ;; 
PAT2) 
    分支2 
    ;; 
... 
*) 
默認分支 
;; 
esac

注:
case支持glob風格的通配符:
*: 任意長度任意字符
?: 任意單個字符
[]:指定範圍內的任意單個字符
a|b: a或b

國際慣例,來個腳本加深理解:

#!/bin/bash
read -p 'Can I ask you out to play?(yes|no)'  go
case    $go    in
[yY]|[yY][eE][sS])
        echo "Let's go."
        ;;
[nN]|[nN][oO])
        echo "That's too bad"
        ;;
*)
        echo "Are you turning me down?"
        ;;
esac
unset go

注:case語句支持glob風格的通配符,用read來交互式輸入變量$go,詢問我能約你出去玩嗎?這時用戶輸入的字符
將會被賦值到變量$go上面,如果變量go的值等於y或是Y或是yes(各種不同大小寫皆可),就會打印let’s go.然後
結束,亦或是變量go的值等於n或是N或是no(各種大小寫皆可),就會打印That’s too bad,然後結束。如果變
量go的值不等於上面的任何一個,就打印Are you turning me down?然後結束。


循環

基本結構

循環執行
        將某代碼段重複運行多次
        重複運行多少次:
                循環次數事先已知
                循環次數事先未知
        有進入條件和退出條件

for循環

普通for循環

for 變量名 in 列表;do 
    循環體
done 

嵌套for循環

for 變量名1 in 列表1;do
    循環體1
    for 變量名2 in 列表2;do
        循環體2
    done
done

執行機制:
依次將列表中的元素賦值給“變量名”; 每次賦值後即執行一次循環體;
直到列表中的元素耗盡,循環結束

列表生成方式:

(1) 直接給出列表 
(2) 整數列表: 
    (a) {start..end} 
    (b) $(seq [start [step]] end) 
(3) 返回列表的命令 
    $(COMMAND) 
(4) 使用glob,如:*.sh 
(5) 變量引用; 
\$@, \$*

國際慣例,來個腳本。
用*打印一個等腰三角形,帶閃爍帶隨機顏色的哦。

if [ $# = 0 ];then 
    read -p "你想打印幾行的等腰三角形:" s
else
    s=$1
fi
    if [ "$s" -gt 0  ] &> /dev/null;then
        for n in `seq  $s` 
        do
        i=$[$s-$n]
        m=$[2*$n-1]
            for i in `seq  $i`; do 
                echo -n  " "
            done    
            for m in `seq  $m`; do
                color=$[$RANDOM%6+1]
                let textcolor=$color+30
                echo -en "\033[1;`echo $textcolor`;5m*\033[0;25m"
                        if [ $s -gt 10 ];then
                            sleep 0.01
                        else
                            sleep 0.05
                        fi
            done 
        echo
        done
    else 
        echo "please...給個大於零的整數吧"
    fi

注:第一步,先判斷這個腳本後面是否跟了參數,如果沒有,就輸出 你想打印幾行的等腰三角形:提示用戶輸入數字,
然後賦值給s(我這裏爲了偷懶只寫了一個字母,生產中變量一定不要只寫一個字母,很容易出錯。),亦或是腳本後面
已經跟了參數也賦值給s,接下來判斷變量s是不是大於0的整數,如果不是就輸出please…給個大於零的整數吧,然後
退出。如果是大於0的整數,就進入第一個for循環,n指的是打印的第幾行,i指得是這一行要打印的空白字符數,m指
的是這一行要打印的*的數量。嵌套第一個for循環,打印這一行要打印的空白字符數i個,嵌套第二個for循環,打印這
一行要打印的*的數量,裏面做了隨機顏色,和閃爍的特效,並用if判斷語句,當行數s大於10時就以更快的速度打印。


while循環

while CONDITION; do 
        循環體 
    done 

CONDITION:循環控制條件;進入循環之前,先做一次判 斷;每一次循環之後會再次做判斷;條件爲“true”,則執行 一次循環;直到條件測試狀態爲“false”終止循環

因此:CONDTION一般應該有循環控制變量;而此變量的值 會在循環體不斷地被修正
進入條件:CONDITION爲true
退出條件:CONDITION爲false

while循環的特殊用法(遍歷文件的每一行):

    while read line; do 
        循環體 
    done < /PATH/FROM/SOMEFILE

依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將 行賦值給變量line


until循環

until循環與while循環恰恰相反,進入條件爲假,爲真時就結束了。

until CONDITION; do 
    循環體 
done 

進入條件: CONDITION 爲false
退出條件: CONDITION 爲true


循環控制語句

continue

用於循環體中
continue [N]:提前結束第N層的本輪循環,而直接進入下一 輪判斷;
最內層爲第1層

while CONDTIITON1; do 
    CMD1 
    ... 
    if CONDITION2; then 
        continue 
    fi 
    CMDn 
    ... 
done

break

用於循環體中
break [N]:提前結束第N層循環,最內層爲第1層

while CONDTIITON1; do 
    CMD1 
    ... 
    if CONDITION2; then 
        break 
    fi 
    CMDn
    ... 
done

shift

循環控制shift命令
shift [n]
用於將參量列表 list 左移指定次數,缺省爲左移一次。
參量列表 list 一旦被移動,最左端的那個參數就從列表中刪除。while 循環遍歷位置參量列表時,常用到 shift
./doit.sh a b c d e f g h
./shfit.sh a b c d e f g h

腳本詳解:

while [ $# -gt 0 ] # or (( $# > 0 )) 
do 
    echo $* 
    shift 
done

注:當輸入的參數大於0時不停的循環下去,比如輸入的參數是aa bb cc ,那麼第一次打印的就是
aa bb cc,經過shift去掉第一個參數,再次循環,打印bb cc,再經過shift,再去掉一個參數,循環,
打印cc,再經過shift去掉一個參數,此時以沒有參數了,循環判斷不大於0了,循環結束。

select循環與菜單

select variable in list 
    do 
        循環體命令 
    done 

select 循環主要用於創建菜單,按數字順序排列的 菜單項將顯示在標準錯誤上,並顯示 PS3 提示符, 等待用戶輸入
用戶輸入菜單列表中的某個數字,執行相應的命令
用戶輸入被保存在內置變量 REPLY 中

select與case
select 是個無限循環,因此要記住用 break 命令退 出循環,或用 exit 命令終止腳本。也可以按 ctrl+c 退出循環
select 經常和 case 聯合使用
與 for 循環類似,可以省略 in list,此時使用位置參量

這裏放上一個我用select與case寫的腳本:

PS3="please choose you menu: "
select menu in exit huimian lamian hulatang yangroutang
do
    case $menu in
    huimian)
        echo10
        ;;
    lamian)
        echo15
        ;;
    hulatang)
        echo5
        ;;
    yangroutang)
        echo20
        ;;
    exit)
        echo "真的不來一點?"
        break
        ;;
    *)
        echo "沒有這個菜..."
    esac
    echo you choose is $menu
    echo you input is $REPLY
done

ღ ღ ღ 如果覺得文章對您有用,不妨贊一下ღ ღ ღ

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章