shell腳本流程控制
shell 腳本變成使用過程中通常需要流程控制,一般情況下是順序執行,在實際使用過程中根據不同情況需要執行不同命令,這時就用到選擇執行比如if、case,有時需要重復執行多次,循環執行比如for、while、until
條件選擇執行語句if
單分支 | 雙分支 |
if 判斷條件;then 條件為真的分支代碼 fi | if 判斷條件; then 條件為真的分支代碼 else 條件為假的分支代碼 fi |
[[email protected] ~]# vim score.sh 1 #!/bin/bash 2 read -p "please input you score :"score 3 if [ $score -eq 100 ];then 4 echo "excellent" 5 elif[ $score -ge 60 ];then 6 echo "keep tring" 7 fi
條件判斷語句case
case 變量引用 in PAT1) 分支1 ;; PAT2) 分支2 ;; *) 默認分支 ;; esac |
例:編寫腳本/root/bin/yesorno.sh,提示用戶輸入yes或no,並判斷用戶輸入的是yes還是no,或是其它信息
[[email protected] ~]# cat /bin/yesorno.sh #!/bin/bash read -p "marry me? please answer yes or no: " ANS case $ANS in [Yy][Ee][Ss]|[Yy]) echo "me too" ;; [Nn][Oo]|[Nn]) echo"my heart broken" ;; *) echo"once again" esac
循環執行語句
for循環循環次數事先已知
依次將列表中的元素賦值給“變量名”; 每次賦值後即執行一次循環體; 直到列表中的元素耗盡,循環結束
方法一 | 方法二:特殊格式 |
for 變量名 in 列表;do 循環體 done | for ((初始化exp1;條件判斷exp2;控制變量的修 正表達式exp3)) 循環體 done |
例:編寫腳本,提示輸入正整數n的值,計算1+2+…+n的總和
方法一: #!/bin/bash read -p "please input positive integer: " n sum=0 for i in `seq 1 $n` do sum=$[$sum+$i] done echo $sum 方法二: [[email protected] ~]# vim sum.sh #!/bin/bash read -p "please input positive integer: " n sum=0 for ((i=1;i<=$n;i++)) do sum=$[$sum+$i] done echo $sum
while循環循環次數事先未知
CONDITION:循環控制條件;進入循環之前,先做一次判斷;每一次循環之後會再次做判斷;條件為“true”,則執行一次循環;直到條件測試狀態為“false”終止循環
因此:CONDTION一般應該有循環控制變量;而此變量的值會在循環體不斷地被修正
進入條件:CONDITION為true
退出條件:CONDITION為false
用法一: | 用法二:while循環的特殊用法(遍歷文件的每一行) |
while cmd ;do cmdN ... done | while read line; do 循環體 done < /PATH/FROM/SOMEFILE 註:依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將行賦值給變量line |
[[email protected] ~]# vim score.sh 1 #!/bin/bash 2 sum=0;i=1 3 while ((i<100)) 4 do 5 sum=$[$sum+$i] 6 let i=$[$i+2] 7 done 8 echo "sum=$sum"
例:掃描/etc/passwd文件每一行,如發現GECOS字段為空,則填充用戶名和單位電話,並提示該用戶的GECOS信息修改成功。
#!/bin/bash while read line ;do comment=`echo $line |cut -d: -f5` username=`echo $line |cut -d: -f1` if [ -z "$comment" ];then chfn -f "$username" $username &> /dev/null chfn -p "0371-61703300" $username &>/dev/null fi done < /app/passwd
until循環有進入條件和退出條件
進入條件: CONDITION 為false
退出條件: CONDITION 為true
until CONDITION; do 循環體 done |
[email protected] ~]# vim score.sh 1 #!/bin/bash 2 sum=0;i=1 3 until ((i>100)) 4 do 5 sum=$[$sum+$i] 6 let i=$[$i+2] 7 done 8 echo "sum=$sum"
select循環語句
select 循環主要用於創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,並顯示 PS3 提示符,
等待用戶輸入
select 是個無限循環,因此要記住用 break 命令退出循環,或用 exit 命令終止腳本。也可以按ctrl+c 退出循環
用戶輸入菜單列表中的某個數字,執行相應的命令
用戶輸入被保存在內置變量 REPLY 中
select variable in list do 循環體命令 done |
循環控制語句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 CMD |
作業:
1、編寫腳本,提示請輸入網絡地址,如192.168.0.0,判斷輸入的網段中主機在線狀態,並統計在線和離線主機各多少
[[email protected] ~]# vim ping.sh #!/bin/bash read -p "please input network (eg:192.168.0.0):" net echo $net |egrep "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).{3}[0-9]|[1-9][ 0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4]" &> /dev/null if [ $? -eq 0 ];then netip=`echo $net |egrep -o ".*\."` for (( i=1;i<255;i++ ));do { ping -c 1 -w1 $netip$i &>/dev/null if [ $? -eq 0 ];then echo "$netip$i is up " echo "$netip$i" >> /app/${netip}txt; fi }& done else echo "please input correct format" fi
2、編寫腳本,實現打印國際象棋棋盤
#!/bin/bash yellow="\033[1;43m \033[0m" red="\033[1;44m \033[0m" for i in {1..8} ; do if [ $[i%2] -eq 0 ] ; then for j in {1..4} ; do echo -en "$yellow$red" done else for j in {1..4} ; do echo -en "$red$yellow" done fi echo done
3、查找連接次數大於10 的拒絕鏈接
方法一:只能對一個大於十次的鏈接進行處理 #!/bin/bash checkinterval=30 while true ;do link=`netstat -nt | sed -rn ‘/^tcp/s/.* (.*):.*$/\1/p‘ |sort |uniq -c |sort -nr |head -n 1` linknum=`echo $link |cut -d " " -f1` ip=`echo $link |cut -d " " -f2` [ $linknum -ge 10 ]&& iptables -A INNPUT -s -$ip -j REJECT echo "$ip at `date +‘%F %T‘` is reject " >> /app/checknet.log sleep $checkinterval done 方法二:當有多個大於十次鏈接都可以進行處理 #!/bin/bash while true ;do link=`netstat -nt | sed -rn ‘/^tcp/s/.* (.*):.*$/\1/p‘ |sort |uniq -c |sort -nr ` echo "$link"|while read fileline ;do linknum=`echo $link |cut -d " " -f1` ip=`echo $link |cut -d " " -f2` if [ $linknum -ge 10 ];then iptables -A INPUT -s -$ip -j REJECT echo "$ip at `date +‘%F %T‘` is reject " >> /app/checknet.log fi done
shell腳本流程控制