流程控制
- 過(guò)程式編程語(yǔ)言:
順序執(zhí)行
選擇執(zhí)行
循環(huán)執(zhí)行
一.條件選擇if語(yǔ)句
類型:選擇執(zhí)行 ?
注意:if語(yǔ)句可嵌套 ?
單分支
if 判斷條件;then
條件為真的分支代碼
fi
雙分支
if 判斷條件; then
條件為真的分支代碼
else
條件為假的分支代碼
fi
多分支
if 判斷條件1; then
條件為真的分支代碼
elif 判斷條件2; then
條件為真的分支代碼
elif 判斷條件3; then
條件為真的分支代碼
else
以上條件都為假的分支代碼
fi ?
逐條件進(jìn)行判斷,第一次遇為“真”條件時(shí)捐康,執(zhí)行其分支劳闹, 而后結(jié)束整個(gè)if語(yǔ)句
注意 type if ——
實(shí)驗(yàn)小練習(xí)
例題1:判斷年齡大小共苛,如果超過(guò)20歲轨域,則顯示"you are too old"如果小于20歲侠坎,則顯示"you are so yong"
嵌套方式:
注意:判斷數(shù)字最好使用[[ "$age" =~ ^[0-9]+$ ]]
例題2:判斷文件是否以.sh后綴
else 條件分支例題
例題:判斷成績(jī)
二.條件判斷:case語(yǔ)句
case 變量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
... *)
默認(rèn)分支
;;
esac
case支持glob風(fēng)格的通配符:
*: 任意長(zhǎng)度任意字符
?: 任意單個(gè)字符
[]:指定范圍內(nèi)的任意單個(gè)字符
a|b: a或b
練習(xí)1:選擇范圍內(nèi)的數(shù)字
練習(xí)2:編輯菜單并選擇
練習(xí)3:判斷yes or no
三.循環(huán)
- 循環(huán)執(zhí)行
將某代碼段重復(fù)運(yùn)行多次
重復(fù)運(yùn)行多少次:
循環(huán)次數(shù)事先已知 循環(huán)次數(shù)事先未知
有進(jìn)入條件和退出條件 ?- for, while, until
(一)for循環(huán)
- 格式:
for "變量名——直接寫變量名 "in 列表;do
循環(huán)體
done ?
執(zhí)行機(jī)制: 依次將列表中的元素賦值給“變量名”; 每次賦值后即執(zhí) 行一次循環(huán)體; 直到列表中的元素耗盡,循環(huán)結(jié)束- 列表生成方式:
(1) 直接給出列表
(2) 整數(shù)列表: (a) {start..end} (b) $(seq [start [step]] end)
(3) 返回列表的命令 $(COMMAND)
(4) 使用glob扁眯,如:.sh
(5) 變量引用壮莹; $@, $
例題1:創(chuàng)建十個(gè)用戶,并設(shè)置密碼
vim create.sh
#!/bin/bash
2 > /root/user.log
3 for id in {1..10} ; do
4 useradd user$id && echo user$id is created
5 password=`tr -dc 'a-zA-Z0-9'< /dev/urandom |head -c 6`
6 echo user$id:$password >> /root/user.log
7 echo $password |passwd --stdin user$id &> /dev/null
8 passwd -e user$id&> /dev/null——登錄后設(shè)置新的密碼
9 done
刪除賬號(hào) : for id in {1..10};do userdel -r user$id ;done
或者:echo user{1..10}|xargs -n1 userdel -r
例題2:和172.18.254這個(gè)網(wǎng)段的ip進(jìn)行連接
1 #!/bin/bash
2 netid=172.18.254
3 > /root/ip.log
4 for id in {1..254};do
5 {
6 if ping -c1 -w1 $netid.$id &> /dev/null;then
7 echo $netid.$id |tee -a /root/ip.log
8 fi
9 } &——后臺(tái)執(zhí)行姻檀,類似并行執(zhí)行命满,節(jié)省時(shí)間
10 done
11 wait——等待時(shí)間help wait
wait: wait [id]
Wait for job completion and return exit status.
(二)while 循環(huán)
(1)while 的使用格式
while 判斷條件 ;do
當(dāng)判斷的條件為真時(shí)绣版,執(zhí)行while 循環(huán)
當(dāng)判斷條件為假時(shí)胶台,不執(zhí)行while 循環(huán)
執(zhí)行原理:當(dāng)使用while 循環(huán)時(shí),首先要判斷條件的真假杂抽,符合條件時(shí)诈唬,進(jìn)入循環(huán)體執(zhí)行一次,然后再次判斷缩麸,直到判斷條件為假時(shí)铸磅,退出循環(huán)不在執(zhí)行
例子1:編寫腳本,求100以內(nèi)所有正奇數(shù)之和
#!/bin/bash
i=1
sum=0
while [ $i -lt 100 ];do
let sum+=i
let i=i+2
done
echo "the sum is $sum"
用for 來(lái)計(jì)算杭朱;
#!/bin/bash
sum=0
for i in {1..100..2};do
let sum+=i
done
echo "the sum is $sum"
例題2阅仔;編寫腳本,提示請(qǐng)輸入網(wǎng)絡(luò)地址弧械,如192.168.0.0八酒,判斷 輸入的網(wǎng)段中主機(jī)在線狀態(tài),并統(tǒng)計(jì)在線和離線主機(jī)各多少
#!/bin/bash
up=0
down=0
hostid=1
read -p "please input the netid:" network
netid=`echo $network| cut -d "." -f1-3`
while [ $hostid -le 10];do
if ping -c1 -w1 $network &> /dev/null;then
echo "the $netid.$hostid is up"
let up++
else
echo "the $netid.$hostid is down"
let down++
fi
let hostid++
done
echo "the up is $up"
echo "the down is $down"
例題三:編寫腳本刃唐,打印九九乘法表
#!/bin/bash
i=1
while [ $i -le 10 ];do
j=1
while [ $j -le 10 ];do
echo -ne "$j*$i=$[j*i]\t"
let j++
done
let i++
echo
done
例題4羞迷;編寫腳本,利用變量RANDOM生成10個(gè)隨機(jī)數(shù)字画饥,輸出 這個(gè)10數(shù)字衔瓮,并顯示其中的最大值和最小值
max=$ran
min=$ran
i=0
while [ $i -le 10 ];do
ran=$RANDOM
echo $ran
if [ $i -eq 0 ];then
max=$ran
min=$ran
fi
if [ $ran -gt $max ];then
max=$ran
elif [ $ran -lt $min];then
min=$ran
fi
let i++
done
echo "the max is $max"
echo "the min is $min"
例題5:編寫腳本,實(shí)現(xiàn)打印國(guó)際象棋棋盤
#!/bin/bash
i=0
while [ $i -lt 8 ];do
j=0
while [ $j -lt 8 ];do
if [ $[ $[j+i]%2 ] -eq 0 ];do
echo -ne "\033[43m \033[0m\t"
else
echo -ne "\033[41m \033[0m\t"
fi
let j++
done
let i++
echo
done
方法二:
#!/bin/bash
i=0
while [ $i -lt 4 ];do
j=0
while [ $j -lt 8 ];do
if [ $j -lt 4 ];then
echo -ne "\033[41m \033[0m\t"
echo -ne "\033[43m \033[0m\t"
if [ $j -eq 3 ];then
echo
fi
else
echo -ne "\033[43m \033[0m"
echo -ne "\033[41m \033[0m"
fi
if [ $j -eq 7 ];then
echo
fi
let j++
done
let i++
done
while 的特殊用法
- while循環(huán)的特殊用法(遍歷文件的每一行):
while read line; do 循環(huán)體 done < /PATH/FROM/SOMEFILE ?
依次讀取/PATH/FROM/SOMEFILE文件中的每一行抖甘,且將 行賦值給變量line
例:查看/etc/passwd中用戶的id报辱,如果小于500則為系統(tǒng)用戶,大于500位普通用戶
while read lines ;do
userid =`echo $lines| cut -d ":" -f3`
username=`echo $lines|cut -d ":" -f1`
if [ $userid-lt 500 ];then
echo "the $username is sysuser"
else echo "the $username is commonuser"
fi
done < /etc/passwd
-
小練習(xí)
掃描/etc/passwd文件每一行单山,如發(fā)現(xiàn)GECOS字段為空碍现,則填 充用戶名和單位電話為62985600,并提示該用戶的GECOS信 息修改成功米奸。
while read lines ;do
GECOS=echo $lines|cut -d ":" -f5
usrename=echo $lines |cut -d ":" -f1
if [ -z $GECOS ];then
chfn -f "$username" -p "62985600" &> /dev/null
echo "the change is successful"
else
echo "the user is not empty"
fi
done < /etc/passwd
- while true; do 循環(huán)體 ?done
示例:檢查httpd 的狀態(tài)昼接,如果處于開啟狀態(tài),就不執(zhí)行悴晰,如果處于關(guān)閉狀態(tài)慢睡,就開啟服務(wù)逐工,每五秒執(zhí)行一次,實(shí)現(xiàn)實(shí)時(shí)監(jiān)控
while true ;do
if killall -0 httpd &> /dev/null ;then
.....
else
systemctl restart httpd &>/dev/null
echo ` date "+%F %T" ` systemctl restart >> /app/httpd.log
fi
sleep5
done
- until false; do 循環(huán)體 ?done
(三)until循環(huán)
- 格式: until 判斷條件 漂辐;do
循環(huán)體
done- 判斷條件為假的時(shí)候進(jìn)入循環(huán)體泪喊,執(zhí)行命令,與while條件相反
判斷條件為為真的時(shí)候髓涯,退出循環(huán)
(四)循環(huán)控制語(yǔ)句continue
用于循環(huán)體中 ?
continue [N]:
提前結(jié)束第N層的本輪循環(huán)袒啼,而直接進(jìn)入下一 輪判斷;最內(nèi)層為第1層
while CONDTIITON1; do
CMD1 ...
if CONDITION2; then
continue
fi
CMDn ...
done例1:
i=0
while [ $I -le 9 ];do
if [ $i -qe 5 ];then
continue
fi
echo i=$i
let i++
done
如果只是不顯示5纬纪,而后續(xù)的數(shù)字繼續(xù)打印蚓再,則
i=0
while [ $i -le 10 ];do
let i++
if [ $i -eq 5 ];then
continue
else
echo i=$i
fi
done
例2
for i in {1..10};do
for j in {1..10};do
echo -n "$j "
if [ %j -eq 5 ];then
continue 2
fi
done
echo
done
此時(shí)為continue 2,所以結(jié)束了第二層的本輪循環(huán),也就是最外層循環(huán)
(五)循環(huán)控制語(yǔ)句break
用于循環(huán)體中 ?
break [N]:提前結(jié)束第N層循環(huán)包各,最內(nèi)層為第1層 ——簡(jiǎn)單來(lái)說(shuō)就是退出第N層整體的循環(huán)
while CONDTIITON1; do
CMD1 ...
if CONDITION2; then
break
fi
CMDn ...
done
例題摘仅;打印行和列
for i in {1..10};do
for j in {1..10};do
echo -n "$j "
[ $j -eq 5 ]&&break
done
echo
done
當(dāng)輸入break 2 時(shí),整個(gè)外層循環(huán)都結(jié)束只打印 "1 2 3 4 5"
(六)循環(huán)控制shift命令
shift [n] ?
用于將參量列表 list 左移指定次數(shù)问畅,缺省為左移一次娃属。 ?
參量列表 list 一旦被移動(dòng),最左端的那個(gè)參數(shù)就從列表中刪 除护姆。
while 循環(huán)遍歷位置參量列表時(shí)膳犹,常用到 shift ?
示例:
whlie [ $# -gt 0 ];do
echo "$*"
shilt
done
因此該命令可以用來(lái)創(chuàng)建用戶
while [ $# -gt 0 ];do
id $i /dev/null && continue
useradd $i && echo $i is created
shift
done
(七)特殊用法 for循環(huán)的特殊格式
- 雙小括號(hào)方法,即((…))格式签则,也可以用于算術(shù)運(yùn)算 ?
*雙小括號(hào)方法也可以使bash Shell實(shí)現(xiàn)C語(yǔ)言風(fēng)格的變量操作
I=10
((I++)) ?
for循環(huán)的特殊格式:
for ((控制變量初始化;條件判斷表達(dá)式;控制變量的修正表達(dá) 式))
do
循環(huán)體
done ?
控制變量初始化:僅在運(yùn)行到循環(huán)代碼段時(shí)執(zhí)行一次 ?
控制變量的修正表達(dá)式:每輪循環(huán)結(jié)束會(huì)先進(jìn)行控制變量修 正運(yùn)算,而后再做條件判斷
例:用for的特殊循環(huán)格式實(shí)現(xiàn)1-100的加法運(yùn)算
sum=0
for (( i=0;i<=100;i++ ));do
let sum+=i
done
echo "the sum is $sum"
unset sum
(八)select循環(huán)與菜單
select variable in list
do
循環(huán)體命令
done ?
select 循環(huán)主要用于創(chuàng)建菜單铐料,按數(shù)字順序排列的 菜單項(xiàng)將顯示在標(biāo)準(zhǔn)錯(cuò)誤上浸卦,并顯示 PS3 提示符筒扒, 等待用戶輸入 ?
用戶輸入菜單列表中的某個(gè)數(shù)字,執(zhí)行相應(yīng)的命令 ?
用戶輸入被保存在內(nèi)置變量 REPLY 中
select 是個(gè)無(wú)限循環(huán),因此要記住用 break 命令退 出循環(huán)桶至,或用 exit 命令終止腳本。也可以按 ctrl+c 退出循環(huán) ?
select 經(jīng)常和 case 聯(lián)合使用 ?
與 for 循環(huán)類似畸陡,可以省略 in list瀑凝,此時(shí)使用位置 參量
例子:選擇菜單
#!/bin/bash
PS3=" please input your menu: "
select menu in lamian chaomian chaofan jiaozi baozi ;do
case $REPLY in
1)
echo "the price is 10"
;;
2)
echo "the price is 15"
;;
3)
echo " the price is 10 "
;;
4)
echo "the price is 20"
;;
5)
echo "the price is 10"
;;
*)
echo "get out!"
break # select 本身是死循環(huán),如果不執(zhí)行break命令愧沟,則不會(huì)退出循環(huán)
;;
esac
done
(九)信號(hào)捕捉trap
- trap '觸發(fā)指令' 信號(hào) 自定義進(jìn)程收到系統(tǒng)發(fā)出的指定信號(hào)后蔬咬,將執(zhí)行觸發(fā)指令 ,而不會(huì)執(zhí)行原操作 ?
- trap '' 信號(hào) 忽略信號(hào)的操作 ?
- trap '-' 信號(hào) 恢復(fù)原信號(hào)的操作 ?
trap -p 列出自定義信號(hào)操作
例:
#!/bin/bash
trap 'echo "please press crtl+c" ' int #此命令是int功能失效沐寺,只是打印"please press crtl+c"
trap -p
for ((i=1;i<=20;i++));do
echo $i
sleep1
done
trap ' ' int # 忽略該操作
trap -p
for ((i=1;i<=20;i++));do
echo $i
sleep1
done
trap '_' int # 恢復(fù)int命令的操作
trap -p
for ((i=1;i<=20;i++));do
echo $i
sleep1
done