2017 08-24 SHELL腳本編程進(jìn)階

  • 流程控制

  • 過(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"


image.png

嵌套方式:


image.png

注意:判斷數(shù)字最好使用[[ "$age" =~ ^[0-9]+$ ]]
例題2:判斷文件是否以.sh后綴
image.png

image.png

else 條件分支例題

例題:判斷成績(jī)


image.png

二.條件判斷: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ù)字


image.png

練習(xí)2:編輯菜單并選擇


image.png

image.png

練習(xí)3:判斷yes or no
image.png
image.png

三.循環(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
image.png
  • 小練習(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

image.png

如果只是不顯示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
image.png

例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
image.png

此時(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


image.png

當(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


    image.png

    因此該命令可以用來(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末林艘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子混坞,更是在濱河造成了極大的恐慌狐援,老刑警劉巖钢坦,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異啥酱,居然都是意外死亡爹凹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門镶殷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)禾酱,“玉大人,你說(shuō)我怎么就攤上這事批钠∮钪玻” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵埋心,是天一觀的道長(zhǎng)指郁。 經(jīng)常有香客問(wèn)我,道長(zhǎng)拷呆,這世上最難降的妖魔是什么闲坎? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮茬斧,結(jié)果婚禮上腰懂,老公的妹妹穿的比我還像新娘。我一直安慰自己项秉,他們只是感情好绣溜,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著娄蔼,像睡著了一般怖喻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上岁诉,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天锚沸,我揣著相機(jī)與錄音,去河邊找鬼涕癣。 笑死哗蜈,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坠韩。 我是一名探鬼主播距潘,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼只搁!你這毒婦竟也來(lái)了绽昼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤须蜗,失蹤者是張志新(化名)和其女友劉穎硅确,沒(méi)想到半個(gè)月后目溉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菱农,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年缭付,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片循未。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陷猫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出的妖,到底是詐尸還是另有隱情绣檬,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布嫂粟,位于F島的核電站娇未,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏星虹。R本人自食惡果不足惜零抬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宽涌。 院中可真熱鬧平夜,春花似錦、人聲如沸卸亮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)兼贸。三九已至段直,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間寝受,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工罕偎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留很澄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓颜及,卻偏偏與公主長(zhǎng)得像甩苛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子俏站,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容