Linux基礎之bash腳本進階篇-循環語句(for,while,until)及其特殊用法

分類:IT技術 時間:2016-10-16

什麽是循環語句、死循環?

循環語句:將一段代碼重復執行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的值

#!/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的不同在於

1、不需要列表,因此可以大大節省內存空間,因為for如果列表很大會占用較多內容空間,對系統性能會造成影響,所以此時while的優越性就顯現出來,它不需要占用很多內存空間,只需要兩個變量的空間及做加法即可。

2、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的唯一差別就在於判斷條件。這兩者其實算是同一種循環語句,只是進入及退出循環的條件正好相反。



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

1、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++調換為止即可正確執行

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

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登錄了,則記錄於日誌中,並退出

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


循環語句的特殊用法(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需要自己在實際寫腳本中細細比較,鑒於本人也是新手,這裏就算想細說也只能望洋興嘆。

本文出自 “張帆-IT的奇幻漂流” 博客,請務必保留此出處http://chawan.blog.51cto.com/9179874/1847024


Tags: 程序員 Linux start 如何 影響

文章來源:


ads
ads

相關文章
ads

相關文章

ad