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