Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

程式設計師聯盟發表於2017-04-16

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

-- 作者 謝恩銘 轉載請註明出處

內容簡介


  1. 前言
  2. while 迴圈
  3. until 迴圈
  4. for 迴圈
  5. 總結
  6. 第五部分第六課預告

1. 前言


上一課 Linux探索之旅 | 第五部分第四課:條件一出,Shell不服 中我們學習了 Shell 中的條件語句。

好吧,我承認,最近幾課的標題有點「雷人」...

有了上一課的基礎,這一課將是很輕鬆的。

我們來學習一個所有程式語言都有的要素:迴圈語句。

迴圈語句使我們得夠重複一個程式碼塊任意多次。這麼有用的機制,Shell 語言當然支援。

Shell 中,主要的迴圈語句有三種:while 迴圈,until 迴圈 和 for 迴圈。我們一一來學習。

2. while 迴圈


在 Shell 中,我們最常用的迴圈是 while 迴圈。

while 是英語「當... 的時候;在… 期間」的意思。

while 迴圈的邏輯是這樣的:

while [ 條件測試 ]
do
    做某些事
done複製程式碼

do 是英語「做」的意思。
done 是英語「完成」的意思。

當然了,我們也可以像在 if 語句中那樣,把 關鍵字 do 放到與條件測試同一行上,但是之間要加分號,如下:

while [ 條件測試 ]; do
    做某些事
done複製程式碼

while 迴圈流程圖:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路
while 迴圈流程圖

我們來寫一個程式,它會請求使用者輸入「 yes 」(英語「是」的意思),如果使用者沒有輸入任何字元或者輸入的字串不是 「yes」,那麼程式就一直請求。

首先,我們建立一個名叫 「 loop.sh 」的檔案( loop 是英語「迴圈」的意思)。

vim loop.sh複製程式碼

在這個檔案中輸入以下內容:

#!/bin/bash

while [ -z $response ] || [ $response != 'yes' ]
do
    read -p 'Say yes : ' response
done複製程式碼

response 是英語「回答」的意思。
say 是英語「說」的意思。

執行:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

我們做了兩個條件測試:

  • response是否是空 :-z $response
  • response 是否不等於「yes」:$response != 'yes'

因為這兩個條件測試之間是用 || (邏輯或)連線的,因此只要兩個條件有一個成立,整個條件測試即成立,就會執行 do 和 done 之間的語句。

可以看到,這個程式非常「任性」,只要我們輸入的不是「 yes 」,它就不停止輸出「 Say yes : 」。真是「咄咄逼人」...

3. until 迴圈


與 while 這個關鍵字相反的有一個 until 關鍵字,until 在英語中是 「直到」的意思。

它也可以實現迴圈,只不過邏輯和 while 迴圈正好相反。

until 迴圈流程圖:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路
until 迴圈流程圖

我們可以用 until 來改寫一下上面的程式:

#!/bin/bash

until [ "$response" = 'yes' ]
do
    read -p 'Say yes : ' response
done複製程式碼

執行結果和 while 迴圈那個是一樣的。

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

4. for 迴圈


for 是英語「對於」的意思。

首先,我們要提醒已經學過主流程式語言(如 C語言,Java,等等)的讀者,Shell 中的 for 迴圈和你已經習慣的 for 迴圈方式略有不同。

我們一起來學習吧。

遍歷列表


for 迴圈可以遍歷一個「取值列表」,基本的邏輯如下:

for 變數 in '值1' '值2' '值3' ... '值n'
do
    做某些事
done複製程式碼

in 是英語「在... 之中」的意思。

for 迴圈流程圖:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路
for 迴圈流程圖

我們來寫一個例子:

#!/bin/bash

for animal in 'dog' 'cat' 'pig'
do
    echo "Animal being analyzed : $animal" 
done複製程式碼

「 Animal being analyzed 」是英語「正在被分析的動物」的意思。

執行:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

可以看到,animal 這個變數依次取了 'dog'(狗), 'cat'(貓), 'pig'(豬) 這三個值。

for 迴圈的取值列表不一定要在程式碼中定義好,我們也可以用一個變數,如下例:

#!/bin/bash

listfile=`ls`

for file in $listfile
do
    echo "File found : $file" 
done複製程式碼

「 File found 」是英語「找到的檔案」的意思。

執行:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

如你所見,上面的程式列出了當前目錄下所有的檔案。

我們還可以簡化上面的程式,不需要用到 listfile 這個變數:

#!/bin/bash

for file in `ls`
do
    echo "File found : $file" 
done複製程式碼

我們可以再改進這個程式,讓它複製當前目錄下的檔案,並且把每個副本的名字修改為「現有名字 + -copy」 (copy 是英語「拷貝」的意思):

#!/bin/bash

for file in `ls`
do
    cp $file $file-copy
done複製程式碼

執行:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

可見,Shell 非常強大。

更常規的 for 迴圈


剛才我們看到的 for 迴圈,和主流程式語言中的語法略有不同,不過我們可以藉助 seq 命令,來實現類似主流程式語言中的 for 迴圈的語法。

seq 是 sequence 的縮寫,是英語「序列」的意思。

來寫一個例子:

#!/bin/bash

for i in `seq 1 10`
do
    echo $i
done複製程式碼

執行:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

以上程式中,「 seq 1 10 」會返回一個取值列表,是從 1 到 10 的整數值。因此,echo 就會遍歷輸出 1 到 10 這 10 個整數。

我們也可以修改預設的取值間隔 ( 1 ),改成我們需要的數值,如下:

#!/bin/bash

for i in `seq 1 2 10`
do
    echo $i
done複製程式碼

執行:

Linux 探索之旅 | 第五部分第五課:迴圈往復,Shell 開路

以上程式中,「 seq 1 2 10 」會返回一個取值列表,是從 1 到 10 的整數值,但是取值間隔是 2,echo 就會遍歷輸出 1 到 10 這 10 個整數中的 1,3,5,7,9 這5個整數。

5. 總結


  1. 我們使用迴圈語句來重複執行一系列指令。

  2. while 迴圈在條件滿足的情況下可以一直重複執行。其中的條件測試語句的機制和上一課的條件語句中的一樣。

  3. until 迴圈和 while 迴圈的邏輯正好相反。

  4. for 迴圈可以遍歷一個「取值列表」,來依次執行相應的指令。在 for 迴圈內部,變數的取值會逐步變化。

6. 第五部分第六課預告


今天的課就到這裡,一起加油吧!

下一課我們學習:一朝Shell函式傾,斗轉星移任我行


微信公眾號「程式設計師聯盟」ProgrammerLeague
我是謝恩銘,在巴黎奮鬥的軟體工程師。
我的簡介
我的經歷
熱愛生活,喜歡游泳,略懂烹飪。
人生格言:“向著標杆直跑”

相關文章