【shell】shell编程(四)-循环语句
上篇我們學習了shell中條件選擇語句的用法。接下來本篇就來學習循環語句。在shell中,循環是通過for, while, until命令來實現的。下面就分別來看看吧。
for
for循環有兩種形式:
for-in語句
基本格式如下:
for var in list docommands done?
list代表要循環的值,在每次循環的時候,會把當前的值賦值給var(變量名而已,隨意定), 這樣在循環體中就可以直接通過$var獲取當前值了。
先來一個例子吧:
#!/bin/bash for str in a b c d e doecho $str done?
以上會根據空格將abcde分割,然后依次輸出出來。
如果以上例子不是以空格分割,而是以逗號(,)分割呢?
#!/bin/bash list="a,b,c,d,e" for str in $list do echo $str done結果輸出a,b,c,d,e
造成這個結果的原因是:for...in循環默認是循環一組通過空格或制表符(tab鍵)或換行符(Enter鍵)分割的值。這個其實是由內部字段分隔符配置的,它是由系統環境變量IFS定義的。當然,既然是由環境變量定義的,那當然也就能修改啊。
?
另一個根據用戶名殺死進程(強制退出用戶)的例子:
首先輸入用戶命,如果用戶未root提示不能殺死root,否則殺死相關進程
#!/bin/bash #input username and kill relactive process for kill user echo "please input username for kill" read username #if username is root ,exit if [ ${username} = 'root' ]thenecho "root can not kill"exit 1 fi #get user PID PID=`/usr/bin/ps -aux | /usr/bin/grep qlq | /usr/bin/awk '$1="qlq" {print $2}'` for killpid in $PID dokill -9 $killpid done echo "killed ok!"?
另外 一個利用for in 實現ls的功能:
#!/bin/bash #for xx in xxx usage for pd in $(/usr/bin/ls /root/sshDemo/) doecho $pd done上面$(/usr/bin/ls /root/sshDemo/)本身返回的就是一行一行的數據,所以可以用做集合
?結果:
[root@VM_0_12_centos sshDemo]# ./testFor.sh addUserBatch.sh delUserBatch.sh killUser.sh testApache.sh testFile.sh testFor.sh testKuohao.sh testNum.sh testSelect.sh testShift.sh?
?
?
修改IFS值
#!/bin/bash #定義一個變量oldIFS保存未修改前的IFS的值 oldIFS=$IFS #修改IFS值,以逗號為分隔符 IFS=$',' list=a,b,c,d,e list2="a b c d e" for var in $list doecho $var done for var2 in $list2 doecho $var2 done #還原IFS的值 IFS=$oldIFS以上第一個循環會分別輸出abcde幾個值。而第二個循環會輸出a b c d e(即未處理)。因為我們把IFS的值設置為逗號了, 當然,不一定要是逗號,想設置什么,你說了算!
?
C語言風格的for循環
bash中c語言風格的for循環遵循如下格式:
for (( variable assignment ; condition ; iteration process ))
一個例子足以說明:
#!/bin/bash for (( i = 0; i <= 10; i++ )) doecho $i done?
上面例子循環11次,從0到10依次輸出。稍微有過編程基礎的都對此應該很熟悉。就不做詳細闡述了。
?
例如:此種風格的for循環批量添加用戶的腳本:
#!/bin/bash #adduser batch echo "please input username:" read username echo "please input number to create:" read number #start to create user for(( i=1;i<="${number}";i++ )) do/usr/sbin/adduser "${username}${i}" > /dev/null 2> /dev/null done #add finished echo "add OK!" echo "please input passwd for users" read password for(( i=1;i<="${number}";i++ )) do/usr/sbin/usermod -p "${password}" "${username}${i}" > /dev/null 2> /de v/null done?
結果:
[root@VM_0_12_centos sshDemo]# ./addUserBatch.sh please input username: ppp please input number to create: 20 add OK! please input passwd for users 123456 [root@VM_0_12_centos sshDemo]# tail -5 /etc/passwd ppp16:x:1017:1017::/home/ppp16:/bin/bash ppp17:x:1018:1018::/home/ppp17:/bin/bash ppp18:x:1019:1019::/home/ppp18:/bin/bash ppp19:x:1020:1020::/home/ppp19:/bin/bash ppp20:x:1021:1021::/home/ppp20:/bin/bash [root@VM_0_12_centos sshDemo]# tail -5 /etc/shadow ppp16:123456:17622:0:99999:7::: ppp17:123456:17622:0:99999:7::: ppp18:123456:17622:0:99999:7::: ppp19:123456:17622:0:99999:7::: ppp20:123456:17622:0:99999:7:::?
?
?
?
例如:批量刪除用戶的腳本:
解釋:去passwd查找第一列過濾輸入的關鍵詞,然后在第一列中查找關鍵詞,如果查到就輸出給users,最后循環刪除:$?用于判斷上一次命令的返回狀態碼,如果返回0代表正常結束,否則就是失敗!
#!/bin/bash #delete user batch echo "please input username word to delete" read word #get All users like word* users=`/usr/bin/grep ${word} /etc/passwd | awk -F: -v word1=${word} 'index($1,wo rd1)>0 {print $1}'` if [ "${users}" = '' ]thenecho "user is does not exist!"exit 1 fi for username in ${users} do/usr/sbin/userdel -rf ${username} > /dev/null 2>/dev/null done if [ "0" = "$?" ]thenecho "delete ok!" elseecho "delete failed!" fi?
?
?
?
while循環
如果你習慣了其它語言的while循環,那么到這兒你又會發現這個while循環有點變態了。與其它編程語言while的不同在于:在bash中的while語句,看起來似乎是結合了if-then語句(參考上一篇)和for循環語句。其基本格式如下:
while test command doother commands done?
?與if-then語句一樣,后面接test命令,如果test后面的命令的退出狀態碼為0. 那么就進入循環,執行do后面的邏輯。要注意在do后面的邏輯中寫條件,避免死循環。
既然是接test命令,那么一切都可以參考if-then的test
示例一:
#!/bin/bash flag=0 while test $flag -le 10 doecho $flag# 如果沒有這句,那么flag的值一直為0,就會無限循環執行flag=$[$flag + 1] done以上判斷flag是否大于或者等于10, 如果滿足條件,那么輸出當前flag的值,然后再將flag的值加1。最終輸出的結果為0到10的結果。
?
結合上一篇文章test的寫法,我們還可以將以上示例變形為如下:
示例二:
#!/bin/bash flag=0 while [ $flag -le 10 ] doecho $flagflag=$[$flag + 1] done?
示例三:
flag=0 while (( $flag <= 10 )) doecho $flagflag=$[$flag + 1] done?
?- shift指令: 參數左移,每執行一次,參數序列順次左移一個位置,$#的值減一。用于分別處理每個參數,移出去的參數不再可用。
例如:shift+while循環實現求和:
?
結果:
[root@VM_0_12_centos sshDemo]# sh -x testShift.sh 1 2 3 5 + '[' 4 -eq 0 ']' + sum=0 + '[' 4 -gt 0 ']' + sum=1 + shift + '[' 3 -gt 0 ']' + sum=3 + shift + '[' 2 -gt 0 ']' + sum=6 + shift + '[' 1 -gt 0 ']' + sum=11 + shift + '[' 0 -gt 0 ']' + echo 11 11?
計算過程:
1 2 3 5 0 2 3 5 1 3 5 3 5 611?
?
總結:對于比較大小的左右都要有空格,例如:[ $# -eq 0 ]
對于計算值的左右都不能有空格,例如:sum=$(($sum+$1))
until循環語句
until語句基本格式如下:
until test commands doother commands done?
?在掌握while循環語句之后, until語句就很簡單了。until語句就是與while語句恰好相反, while語句是在test命令退出狀態碼為0的時候執行循環, 而until語句是在test命令退出狀態碼不為0的時候執行。
示例:
#!/bin/bash flag=0 until (( $flag > 10 )) doecho $flagflag=$[ $flag + 1 ] done?
以上輸出0到10的值。until后面的條件與上面while例子完全相反。
好啦,到此,我們學完了shell的循環語句啦。不過上面我們寫的循環語句都是根據條件執行完畢,如果我們在執行的過程中想退出,該怎么辦?接下來就繼續看看怎么控制循環語句。
控制循環
與其它編程語言一樣,shell是通過break和continue命令來控制循環的。下面就分別來看看二者的基本用法:
break
示例一:
#!/bin/bash for (( flag=0; flag <= 10; flag++ )) doif (( $flag == 5 ))thenbreakfiecho $flag done?
以上當flag的值為5的時候,退出循環。輸出結果為0-4的值。
示例二:
#!/bin/bash flag=0 while (( $flag < 10 )) dofor (( innerFlag=0; innerFlag < 5; innerFlag++ ))doif (( $innerFlag == 2 ))thenbreakfiecho "innerFlag=$innerFlag"doneecho "outerFlag=$flag" done?
以上代碼在執行內部循環for的時候,當innerFlag值為2的時候就會跳出到外層的while循環, 由于外層循環一直flag都為0, 所以while會成為一個死循環,不停的輸出:
...
innerFlag=0
innerFlag=1
outerFlag=0
...
break 可后接數字,用于表示退出當前循環的外層的第幾層循環。
示例三:
#!/bin/bash flag=0 while (( $flag < 10 )) dofor (( innerFlag=0; innerFlag < 5; innerFlag++ ))doif (( $innerFlag == 2 ))then# 2表示外面一層循環break 2fiecho "innerFlag=$innerFlag"doneecho "outerFlag=$flag" done?
與上面例子相比,本例就只是在break后面跟了個數字2,表示退出外面的第一層循環。最終輸出:
innerFlag=0
innerFlag=1
continue
continue表示終止當前的一次循環,進入下一次循環,注意,continue后面的語句不會執行。
continue的語法與break一樣,因此,就只做一個示例演示啦。
示例:
flag=0 while (( $flag <= 10 )) doif (( $flag == 5 ))thenflag=$[$flag+1]continuefiecho "outerFlag=$flag"for (( innerFlag=11; innerFlag < 20; innerFlag++ ))doif (( $innerFlag == 16 ))thenflag=$[$flag+1]continue 2fiecho "innerFlag=$innerFlag"done done?
以上例子: 當for循環中innerFlag的值為16的時候會跳到外層while循環,當外層循環的flag的值為5的時候,會直接跳過本次循環,然后進入下一次循環,因此在輸出的結果中,不會出現outerFlag=5的情況。
?
接下來可以學習shell學習五:http://www.cnblogs.com/qlqwjy/p/7746009.html
?
轉載于:https://www.cnblogs.com/qlqwjy/p/7746001.html
總結
以上是生活随笔為你收集整理的【shell】shell编程(四)-循环语句的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 04-课后作业1-字符串加密
- 下一篇: 案例