Linux基礎之bash腳本進階篇-循環語句(for,while,until)

20160909 補充break與continue的區別程序員



什麼是循環語句、死循環?docker

循環語句:將一段代碼重複執行0、1或屢次。編程

到底要重複運行多少次?以及咱們如何設定循環語句的重複次數?bash

爲了解決上面的問題因而就有了進入條件退出條件ide

進入條件:條件知足時進入循環。工具

退出條件:不符合條件退出循環。性能

一種特殊的循環:死循環測試

死循環:在編程中,一個沒法靠自身的控制終止的循環稱爲"死循環"。死循環的出現有兩種狀況:ui

一、因程序須要刻意寫的;二、因程序員的失誤形成的。spa

第二種的死循環一般會形成比較嚴重的程序錯誤,甚至會所以而影響物理機。所以死循環的使用須要合理的設計

                                                         實驗環境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的值

#!/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結果以下

[root@docker hmworks]# sh 0906-1
The sum is : 55

上面使用了第一種的整數列表中的第一種形式,這裏若是是「1+2+...+n」這種形式那麼{start..end}就再也不適用,此時就只能使用$(seq start [[step]end])。下面再舉一個例子說明

示例:計算「1+2+...+n」的值

#!/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"

下面執行該腳本

[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])

#!/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"

執行該腳本

[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的值

#!/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"

執行腳本,查看其是否正確執行

[root@docker hmworks]# sh 0906-3
The sum is : 55

while與for的不一樣在於

一、不須要列表,所以能夠大大節省內存空間,由於for若是列表很大會佔用較多內容空間,對系統性能會形成影響,因此此時while的優越性就顯現出來,它不須要佔用不少內存空間,只須要兩個變量的空間及作加法便可。

二、while須要修正體來不斷修正變量,最終在符合退出條件時結束循環

………………………………………………………………………………………………………………………

until循環

until語句使用格式:

    until CONDITION; do

    循環體

    done


CONDITION:循環控制條件;進入循環以前,先作一次判斷;每一次循環以後會再次作判斷;條件爲「false」,則執行一次循環;直到條件測試狀態爲「true」終止循環;

所以:CONDTION通常應該有循環控制變量;而此變量的值會在循環體不斷地被修正;

進入條件:CONDITION爲false

退出條件:CONDITION爲true

until的用法同while,惟一的區別在於進入循環與退出循環的條件相反

以相同的例子來體會兩者的區別

………………………………………………………………………………………………………………………

示例:計算1+2+...+10的值

#!/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"

執行腳本,查看結果是否正確輸出

[root@docker hmworks]# sh 0906-4
The sum is : 55

經過比較while與until的惟一差異就在於判斷條件。這二者其實算是同一種循環語句,只是進入及退出循環的條件正好相反。



循環控制語句(用於循環體中)

一、continue [N]:提早結束第N層的本輪循環,而直接進入下一輪判斷;

其使用格式

    while CONDTIITON1; do

      CMD1

        ...

      if CONDITION2; then

       continue

      fi

      CMDn

       ...

    done

………………………………………………………………………………………………………………………

示例:求100之內全部偶數之和;要求循環遍歷100之內的所正整數

#!/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"

執行腳本,查看結果是否正確顯示

[root@docker hmworks]# sh 0906-5
The even number sum : 2550


以前我寫這個腳本時是這麼寫的

#!/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++調換爲止便可正確執行

………………………………………………………………………………………………………………………

二、break [N]:提早結束循環;

其使用格式

    while CONDTIITON1; do

      CMD1

       ...

      if CONDITION2; then

         break

      fi

      CMDn

       ...

    done

break的使用一般是與死循環同時出現的,下面來介紹如何建立死循環

建立死循環:

    while true; do

     循環體

    done


    until false; do

     循環體

    done

………………………………………………………………………………………………………………………

示例:每隔3秒鐘到系統上獲取已經登陸的用戶的信息;若是docker登陸了,則記錄於日誌中,並退出

#!/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

運行腳本

[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用戶登錄

wKiom1fOxNDjKdg8AAA43X5AK3w176.gif

wKiom1fOxNDggGm0AABazt_e-04945.gif

wKioL1fOxNCQuQH2AAALsOuQOWI360.gif

docker用戶登錄後查看/tmp/user.log文件

wKioL1fOxNCQMHjGAAAJkfdg2OE565.gif

#########################################################################################

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號;

#!/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

運行腳本

wKiom1fOxvHyCEm2AAA1-ZyutMI547.gif

………………………………………………………………………………………………………………………

for循環的特殊格式

for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式)); do

    循環體

done


控制變量初始化:僅在運行到循環代碼段時執行一次;

條件判斷表達式:在什麼條件下進行循環;

控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,然後再作條件判斷;

示例:求100之內所正整數之和

#!/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"

運行腳本,查看結果是否正確

[root@docker hmworks]# sh 0906-8
The sum is : 5050

for的這種格式減小了代碼量,看着更簡潔,不過其限制是只適用於有數字出現的循環,如果對某目錄下的全部文件進行某種循環的執行就不適應了。


循環嵌套

在本文的最後再以一題體會下循環嵌套的神奇

示例:打印九九乘法表

#!/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須要本身在實際寫腳本中細細比較,鑑於本人也是新手,這裏就算想細說也只能望洋興嘆。

相關文章
相關標籤/搜索