Linux基础之bash脚本进阶篇-循环语句(for,while,until)
20160909 補(bǔ)充break與continue的區(qū)別
什么是循環(huán)語句、死循環(huán)?
循環(huán)語句:將一段代碼重復(fù)執(zhí)行0、1或多次。
到底要重復(fù)運(yùn)行多少次?以及我們?nèi)绾卧O(shè)定循環(huán)語句的重復(fù)次數(shù)?
為了解決上面的問題于是就有了進(jìn)入條件與退出條件。
進(jìn)入條件:條件滿足時(shí)進(jìn)入循環(huán)。
退出條件:不符合條件退出循環(huán)。
一種特殊的循環(huán):死循環(huán)
死循環(huán):在編程中,一個(gè)無法靠自身的控制終止的循環(huán)稱為"死循環(huán)"。死循環(huán)的出現(xiàn)有兩種情況:
1、因程序需要刻意寫的;2、因程序員的失誤造成的。
第二種的死循環(huán)通常會(huì)造成比較嚴(yán)重的程序錯(cuò)誤,甚至?xí)虼硕绊懳锢頇C(jī)。因此死循環(huán)的使用需要合理的設(shè)計(jì)。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?實(shí)驗(yàn)環(huán)境CentOS7.2
本文重要的三個(gè)循環(huán)語句:for、while、until
………………………………………………………………………………………………………………………
for循環(huán)
for語句的使用格式:
????for?NAME in LIST(列表);?do
????循環(huán)體
????done
列表生成方式:
(1)?整數(shù)列表
? ? {start..end}
? ? $(seq start [[step]end])
(2)?glob
? ? /etc/rc.d/rc3.d/K*
(3)?命令
………………………………………………………………………………………………………………………
下面以一個(gè)例子看看for的具體作用
示例:計(jì)算1+2+...+10的值
| 1 2 3 4 5 6 7 8 9 | #!/bin/bash #sum?the?value?of?"1+2+...+10" #author?chawan? #date:20160906 declare?-i?sum=0 for?x?in?{1..10};do ???let?sum+=$x done echo?"The?sum?is?:?$sum" |
運(yùn)行腳本0906-1結(jié)果如下
| 1 2 | [root@docker?hmworks]#?sh?0906-1 The?sum?is?:?55 |
上面使用了第一種的整數(shù)列表中的第一種形式,這里如果是“1+2+...+n”這種形式那么{start..end}就不再適用,此時(shí)就只能使用$(seq start [[step]end])。下面再舉一個(gè)例子說明
示例:計(jì)算“1+2+...+n”的值
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/bin/bash #sum?“1+2+...+n” #author?chawan #date:20160906 declare?-i?sum=0 #以交互的方式輸入一個(gè)正整數(shù) read?-p?"Please?inset?a?number?:"?num #判斷輸入的數(shù)是否為空,為空則提示并退出 [?-z?$num?]?&&?echo?"Please?input?a?number!"?&&?exit?1 #判斷輸入的是否是正整數(shù),若是則執(zhí)行循環(huán),若不是提示輸入正整數(shù)并退出 if?[[?$num?=~?^[1-9][0-9]{0,}$?]]?;?then ???for?i?in?{1..$num};do??? #for?i?in?`seq?1?$num`;do ???????let?sum+=$i ???????#sum=$[$sum+$i]?這種方式也可以不過不夠簡(jiǎn)練 ???done else ??echo?"Error?:?please?input?a?positive?integer"?&&?exit?2 fi #顯示最后的和 echo?"The?sum?is?:?$sum" |
下面執(zhí)行該腳本
| 1 2 3 4 | [root@docker?hmworks]#?sh?0906-2 Please?inset?a?number?:8 0906-2:行14:?let:?sum+={1..8}:?語法錯(cuò)誤:?期待操作數(shù)?(錯(cuò)誤符號(hào)是?"{1..8}") The?sum?is?:?0 |
該結(jié)果說明{start..end}形式不適用于有變量出現(xiàn)的情況,既然這個(gè)不行就來試試$(seq start [[step]end])
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #!/bin/bash #sum?“1+2+...+n” #author?chawan #date:20160906 declare?-i?sum=0 #以交互的方式輸入一個(gè)正整數(shù) read?-p?"Please?inset?a?number?:"?num #判斷輸入的數(shù)是否為空,為空則提示并退出 [?-z?$num?]?&&?echo?"Please?input?a?number!"?&&?exit?1 #判斷輸入的是否是正整數(shù),若是則執(zhí)行循環(huán),若不是提示輸入正整數(shù)并退出 if?[[?$num?=~?^[1-9][0-9]{0,}$?]]?;?then ???for?i?in?`seq?1?$num`;do ???????let?sum+=$i ???????#sum=$[$sum+$i] ???done else ??echo?"Error?:?please?input?a?positive?integer"?&&?exit?2 fi #顯示最后的和 echo?"The?sum?is?:?$sum" |
執(zhí)行該腳本
| 1 2 3 4 5 6 | [root@docker?hmworks]#?sh?0906-2 Please?inset?a?number?:10 The?sum?is?:?55 [root@docker?hmworks]#?sh?0906-2 Please?inset?a?number?:100 The?sum?is?:?5050 |
該結(jié)果表明$(seq start [[step]end])適用性更好,因此一般建議使用它。
列表的glob與命令這兩種就不再具體演示。大家感興趣可以自己嘗試下做個(gè)實(shí)驗(yàn)體會(huì)體會(huì)。
………………………………………………………………………………………………………………………
while循環(huán)
while語句使用格式:
????while?CONDITION;?do
????循環(huán)體
????done
CONDITION:循環(huán)控制條件;進(jìn)入循環(huán)之前,先做一次判斷;每一次循環(huán)之后會(huì)再次做判斷;條件為“true”,則執(zhí)行一次循環(huán);直到條件測(cè)試狀態(tài)為“false”終止循環(huán);
因此:CONDTION一般應(yīng)該有循環(huán)控制變量;而此變量的值會(huì)在循環(huán)體不斷地被修正;
進(jìn)入條件:CONDITION為true;
退出條件:CONDITION為false
………………………………………………………………………………………………………………………
示例:計(jì)算1+2+...+10的值
| 1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash #sum?the?value?of?"1+2+...+10"??while #author?chawan #date:20160906 #為了嚴(yán)謹(jǐn)起見,事先聲明變量sum及i為整數(shù)型 declare?-i?sum=0 declare?-i?i=1 while?[?$i?-le?10?];do ????let?sum+=$i????#sum=$[$sum+$i]的簡(jiǎn)寫形式 ????let?i++????????#不斷修正變量體 done echo?"The?sum?is?:?$sum" |
執(zhí)行腳本,查看其是否正確執(zhí)行
| 1 2 | [root@docker?hmworks]#?sh?0906-3 The?sum?is?:?55 |
while與for的不同在于:
1、不需要列表,因此可以大大節(jié)省內(nèi)存空間,因?yàn)閒or如果列表很大會(huì)占用較多內(nèi)容空間,對(duì)系統(tǒng)性能會(huì)造成影響,所以此時(shí)while的優(yōu)越性就顯現(xiàn)出來,它不需要占用很多內(nèi)存空間,只需要兩個(gè)變量的空間及做加法即可。
2、while需要修正體來不斷修正變量,最終在符合退出條件時(shí)結(jié)束循環(huán)。
………………………………………………………………………………………………………………………
until循環(huán)
until語句使用格式:
? ??until?CONDITION;?do
????循環(huán)體
????done
CONDITION:循環(huán)控制條件;進(jìn)入循環(huán)之前,先做一次判斷;每一次循環(huán)之后會(huì)再次做判斷;條件為“false”,則執(zhí)行一次循環(huán);直到條件測(cè)試狀態(tài)為“true”終止循環(huán);
因此:CONDTION一般應(yīng)該有循環(huán)控制變量;而此變量的值會(huì)在循環(huán)體不斷地被修正;
進(jìn)入條件:CONDITION為false;
退出條件:CONDITION為true
until的用法同while,唯一的區(qū)別在于進(jìn)入循環(huán)與退出循環(huán)的條件相反。
以相同的例子來體會(huì)二者的區(qū)別
………………………………………………………………………………………………………………………
示例:計(jì)算1+2+...+10的值
| 1 2 3 4 5 6 7 8 9 10 11 | #!/bin/bash #sum?the?value?of?"1+2+...+10"??until #author?chawan #date:20160906 declare?-i?sum=0 declare?-i?i=1 until?[?$i?-gt?10?];do ????let?sum+=$i ????let?i++ done echo?"The?sum?is?:?$sum" |
執(zhí)行腳本,查看結(jié)果是否正確輸出
| 1 2 | [root@docker?hmworks]#?sh?0906-4 The?sum?is?:?55 |
通過比較while與until的唯一差別就在于判斷條件。這兩者其實(shí)算是同一種循環(huán)語句,只是進(jìn)入及退出循環(huán)的條件正好相反。
循環(huán)控制語句(用于循環(huán)體中)
1、continue?[N]:提前結(jié)束第N層的本輪循環(huán),而直接進(jìn)入下一輪判斷;
其使用格式:
? ? while?CONDTIITON1;?do
? ? ? CMD1
? ? ? ? ...
? ? ? if?CONDITION2;?then
? ? ? ?continue
? ? ? fi
? ? ? CMDn
? ? ? ?...
? ? done
………………………………………………………………………………………………………………………
示例:求100以內(nèi)所有偶數(shù)之和;要求循環(huán)遍歷100以內(nèi)的所正整數(shù)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/bin/bash #求100以內(nèi)所有偶數(shù)之和;要求循環(huán)遍歷100以內(nèi)的所正整數(shù) #author?chawan #date:20160906 declare?-i?i=1 declare?-i?sum=0 while?[?$i?-le?100?];do ????let?i++ #如果為奇數(shù)則跳過該循環(huán) ????if?[?$[${i}%2]?-eq?1?];then ??????continue ????fi ????let?sum+=$i done echo??"The?even?number?sum?:?$sum" |
執(zhí)行腳本,查看結(jié)果是否正確顯示
| 1 2 | [root@docker?hmworks]#?sh?0906-5 The?even?number?sum?:?2550 |
之前我寫這個(gè)腳本時(shí)是這么寫的
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/bin/bash #求100以內(nèi)所有偶數(shù)之和;要求循環(huán)遍歷100以內(nèi)的所正整數(shù) #author?chawan #date:20160906 declare?-i?i=1 declare?-i?sum=0 while?[?$i?-le?100?];do ????let?sum+=$i #如果為奇數(shù)則跳過該循環(huán),直接進(jìn)入下一輪判斷后面的程序不再執(zhí)行 ????if?[?$[${i}%2]?-eq?1?];then ??????continue ????fi ????let?i++ done echo??"The?even?number?sum?:?$sum" |
這就是我個(gè)人由于對(duì)continue的理解不夠準(zhǔn)確而造成的死循環(huán)。
由于continue是跳過其所在循環(huán),直接進(jìn)入下一輪判斷,后面的語句都不再執(zhí)行。
當(dāng)時(shí)沒注意這點(diǎn)所以錯(cuò)誤地把i++放在后面,這就導(dǎo)致若i起始值為奇數(shù)那么它就一直在重復(fù)執(zhí)行。
這里只要將let sum+=$i與let i++調(diào)換為止即可正確執(zhí)行。
………………………………………………………………………………………………………………………
2、break?[N]:提前結(jié)束循環(huán);
其使用格式:
? ? while?CONDTIITON1;?do
? ? ? CMD1
? ? ? ?...
? ? ? if?CONDITION2;?then
? ? ? ? ?break
? ? ? fi
? ? ? CMDn
? ? ? ?...
? ? done
break的使用通常是與死循環(huán)同時(shí)出現(xiàn)的,下面來介紹如何創(chuàng)建死循環(huán)
創(chuàng)建死循環(huán):
? ? while?true;?do
? ? ?循環(huán)體
? ? done
? ? until?false;?do
? ? ?循環(huán)體
? ? done
………………………………………………………………………………………………………………………
示例:每隔3秒鐘到系統(tǒng)上獲取已經(jīng)登錄的用戶的信息;如果docker登錄了,則記錄于日志中,并退出;
| 1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash #每隔3秒鐘到系統(tǒng)上獲取已經(jīng)登錄的用戶的信息;如果docker用戶登錄,則記錄于日志中,并退出腳本 #author?chawan #date:20160906 while?true;do ?????if?who?|?grep?"^docker\>"?$>?/dev/null;then ?????????break ?????fi ?????sleep?3 ?????echo?"docker?is?not?login" done echo?"docker?logged?on."?>>?/tmp/user.log |
運(yùn)行腳本
| 1 2 3 4 5 6 7 | [root@docker?hmworks]#?sh?0906-6 docker?is?not?login docker?is?not?login docker?is?not?login docker?is?not?login docker?is?not?login docker?is?not?login |
為了驗(yàn)證該腳本,下面我們使用docker用戶登陸
docker用戶登陸后查看/tmp/user.log文件
#########################################################################################
break與continue語句的區(qū)別:
break語句和continue語句都可以位于各種循環(huán)體內(nèi),用于控制當(dāng)前的循環(huán)流程。但,break語句是直接退出當(dāng)前的循環(huán)結(jié)構(gòu),轉(zhuǎn)向執(zhí)行循環(huán)體后面的語句;而continue語句則只是跳過當(dāng)前循環(huán)體中continue語句后面的語句,轉(zhuǎn)向當(dāng)前循環(huán)體的起始位置,重新執(zhí)行下一次循環(huán),并沒有退出當(dāng)前的循環(huán)結(jié)構(gòu)。
這是兩者最本質(zhì)的區(qū)別:break跳出當(dāng)前循環(huán),continue沒有跳出當(dāng)前循環(huán)。
循環(huán)語句的特殊用法(while及for)
while循環(huán)的特殊用法(遍歷文件的每一行):
其使用格式:
? ? while?read line;?do
? ? ? 循環(huán)體
? ? done?< /PATH/FROM/SOMEFILE
依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將行賦值給變量line
………………………………………………………………………………………………………………………
示例:找出其ID號(hào)為偶數(shù)的所有用戶,顯示其用戶名及ID號(hào);
| 1 2 3 4 5 6 7 8 9 10 | #!/bin/bash #找出其ID號(hào)為偶數(shù)的所有用戶,顯示其用戶名及ID號(hào) #author?chawan #date:20160906 while?read?line;do ??if?[?$[`echo?$line?|?cut?-d:?-f3`%2]?-eq?0?];then ????echo?-e?-n?"username:?`echo?$line|cut?-d:?-f1`\t" ????echo?"uid:`echo?$line|cut?-d:?-f3`" ??fi done?<?/etc/passwd |
運(yùn)行腳本
………………………………………………………………………………………………………………………
for循環(huán)的特殊格式:
for?((控制變量初始化;條件判斷表達(dá)式;控制變量的修正表達(dá)式));?do
? ? 循環(huán)體
done
控制變量初始化:僅在運(yùn)行到循環(huán)代碼段時(shí)執(zhí)行一次;
條件判斷表達(dá)式:在什么條件下進(jìn)行循環(huán);
控制變量的修正表達(dá)式:每輪循環(huán)結(jié)束會(huì)先進(jìn)行控制變量修正運(yùn)算,而后再做條件判斷;
示例:求100以內(nèi)所正整數(shù)之和
| 1 2 3 4 5 6 7 8 9 | #!/bin/bash #求100以內(nèi)所正整數(shù)之和 #author?chawan #date:20160906 declare?-i?sum=0 for?((i=1;i<=100;i++));do ?????let?sum+=$i done echo?"The?sum?is?:?$sum" |
運(yùn)行腳本,查看結(jié)果是否正確
| 1 2 | [root@docker?hmworks]#?sh?0906-8 The?sum?is?:?5050 |
for的這種格式減少了代碼量,看著更簡(jiǎn)潔,不過其限制是只適用于有數(shù)字出現(xiàn)的循環(huán),若是對(duì)某目錄下的所有文件進(jìn)行某種循環(huán)的執(zhí)行就不適應(yīng)了。
循環(huán)嵌套
在本文的最后再以一題體會(huì)下循環(huán)嵌套的神奇
示例:打印九九乘法表
| 1 2 3 4 5 6 7 8 9 10 | #!/bin/bash #打印九九乘法表 #author?chawan #date?:?20160906 for((j=1;j<=9;j++));do ???for((i=1;i<=j;i++))do ??????echo?-e?-n?"${i}X${j}=$[$i*$j]\t" ???done echo done |
? ? 我在剛剛接觸循環(huán)嵌套時(shí)各種暈,循環(huán)嵌套不是沒有目的的亂用,而是根據(jù)自己的需求有目的的使用,比如要打印99乘法表,開始要分析99乘法表的規(guī)律,分析后我們發(fā)現(xiàn)它橫行是連續(xù)的,因此要用到一個(gè)循環(huán)(通常在遇到連續(xù)的內(nèi)容都會(huì)用到循環(huán))它的列也是連續(xù)的,因此又用到一個(gè)循環(huán),而99乘法表又是由兩個(gè)變化的量構(gòu)成,綜上我們就可以確定,需要使用兩個(gè)變量,這兩個(gè)變量分別要用到循環(huán),而一個(gè)變量又受到另一個(gè)變量的限制,因此這個(gè)受限的變量就是被嵌套的主。問題分析到這里,我們解決這個(gè)問題要用到的工具都找出來了:兩個(gè)變量,每個(gè)變量對(duì)應(yīng)一個(gè)循環(huán),同時(shí)一個(gè)變量受到另一個(gè)變量的限制,也就是說它需要在其循環(huán)內(nèi)進(jìn)行嵌套。
? ? 下面就是靠自己去使用工具解決問題了。我相信大家這點(diǎn)應(yīng)該都不成問題,問題就分析到這里。
小結(jié):
? ? 本文主要介紹什么是循環(huán),死循環(huán),bash常用的三種循環(huán)語句for、while、until及循環(huán)控制語句continue、break
? ? 在本文結(jié)尾又介紹了while的特殊用法(遍歷文件中的每一行),for的c語言格式。
至于什么時(shí)候用for什么時(shí)候用while需要自己在實(shí)際寫腳本中細(xì)細(xì)比較,鑒于本人也是新手,這里就算想細(xì)說也只能望洋興嘆。
本文轉(zhuǎn)自 紫色的茶碗 51CTO博客,原文鏈接:http://blog.51cto.com/chawan/1847024,如需轉(zhuǎn)載請(qǐng)自行聯(lián)系原作者
總結(jié)
以上是生活随笔為你收集整理的Linux基础之bash脚本进阶篇-循环语句(for,while,until)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]利用ASP.NET 2.0创建自定
- 下一篇: activePerl的PPM如何使用ht