『忘了再學』Shell流程控制 — 36、for迴圈介紹

繁華似錦Fighting發表於2022-06-21

1、for迴圈介紹

for迴圈是固定迴圈,也就是在迴圈時已經知道需要進行幾次的迴圈,有時也把for迴圈稱為計數迴圈。

在Shell中for迴圈的語法有如下兩種:

# 語法1:
for 變數 in 值1 值2 值3 …
    do
        程式
    done

這種語法中for迴圈的次數,取決於in後面值的個數(空格分隔),有幾個值就迴圈幾次,並且每次迴圈都把該值賦予變數。也就是說,假設in後面有三個值,for會迴圈三次,第一次迴圈會把值1賦予變數,第二次迴圈會把值2賦予變數,以此類推。

# 語法2:
for((初始值;迴圈控制條件;變數變化))
    do
        程式
    done

語法二中需要注意:

  • 初始值:在迴圈開始時,需要給某個變數賦予初始值,如i=1
  • 迴圈控制條件:用於指定變數迴圈的次數,如i<=100,則只要i的值小於等於100,迴圈就會繼續;
  • 變數變化:每次迴圈之後,變數該如何變化,如i=i+1,代表每次迴圈之後,變數i的值都加1。

2、示例

語法一舉例:

需求:列印時間。

# 建立指令碼檔案
[root@localhost ~]# vim sh/for.sh
#!/bin/bash

for time in morning noon afternoon evening
    do
        echo "This time is $time!"
    done

執行指令碼結果:

[root@localhost tmp]# chmod 755 for1.sh
[root@localhost tmp]# ./for1.sh
This time is morning!
This time is noon!
This time is afternoon!
This time is evening!

語法二舉例:

語法二就和其他語言中的for迴圈類似了,也就是事先決定迴圈次數的固定迴圈了。

需求:從1加到100。

#!/bin/bash

# 定義一個求和變數sum
sum=0

# 定義迴圈100次
# 在Shell中如果要進行數學運算,需要用雙小括號括起來,才識別括號裡面是數值運算。
for((i=1;i<=100;i=i+1))
    do
        # 每次迴圈給變數sum賦值
        sum=$(($sum+$i))

    done

# 輸出1加到100的和
echo "The sum of 1+2+...+100 is :$sum"

3、for迴圈總結

  • 第一種格式的for迴圈是最常見的Shell迴圈方式。
  • 第二種格式的for迴圈適合做數學運算,可以方便的指定迴圈次數。

4、練習:批量解壓縮指令碼

方式一:批量解壓縮

# 建立指令碼檔案auto-tar.sh
[root@localhost ~]# vim sh/auto-tar.sh

# 批量解壓縮指令碼
#!/bin/bash

# 進入壓縮包目錄。
cd /tmp/sh/tar

# 把tar目錄中的所有壓縮包的檔名,儲存到tar.log檔案中。
# 單>是覆蓋。
# 而且tar.log中內容是每一個檔名是一行。
ls *.tar.gz>tar.log
# 把tar目錄中.tgz型別的壓縮包的名字也追加到tar.log檔案中。
# 雙>>是追加。
ls *.tgz>>tar.log &>/dev/null
# 提示:用上面的方式,把需要解壓的所有型別的壓縮檔案的名稱,都存入到tar.log檔案中。

# 讀取tar.log檔案的內容,檔案中有多少個值,就會迴圈多少次,
# 每次迴圈把檔名賦予變數i
for i in $(cat tar.log)
    do
        # 解壓縮,並把所有輸出都丟棄
        tar -zxvf $i &>/dev/null

        # 注意如果還有其他格式的壓縮包,需要在這裡進行if判斷,
        # 分別針對不同格式的壓縮檔案進行解壓。
        # 方式二也一樣。
    done

# 刪除臨時檔案tar.log,因為指令碼執行完就沒有作用了。
rm -rf /tmp/sh/tar/tar.log

說明:

第一種方式的for迴圈,in後有幾個值,就迴圈幾次,值之間要有空格分隔。

tar.log檔案中存放的是6個壓縮包的檔名,且每一個檔名佔一行,

[root@localhost tmp]# cat tar.log
apr-1.4.6.tar.gz
apr-util-1.4.1.tar.gz
httpd-2.4.7.tar.gz I
mysq1-5.5.23.tar.gz
php-5.6.15.tar.gz
phpMyAdmin-4.1.4-al1-languages.tar.gz

這樣的格式,就相當於一行算一個值,這樣就可以迴圈6次,每次的值就是一個壓縮包的檔名,

這樣就完成了所需檔案的批量解壓縮。

方式二:批量解壓縮

for迴圈的第二種方式進行批量解壓縮,有兩個需要注意的內容。

  • 第一:需要知道壓縮包的總個數,因為我需要用for迴圈的第二種格式進行批量解壓,就需要先知道要迴圈幾次。
    解決方式:把所有需要解壓檔案的檔名儲存到一個檔案中(臨時檔案),這時候所需解壓縮檔案的檔名就變成了字串,然後通過wc命令進行統計就可以。
  • 第二:需要把每個壓縮包的名稱提取出來,賦值在變數中。
    就是第一次迴圈,變數中賦值的是第一個壓縮包的檔名,第二次迴圈,變數中賦值第二個壓縮包的檔名,然後就能夠用tar命令解壓該壓縮包了。
#/bin/bash

# 進入壓縮包目錄。
cd /tmp/sh/tar

# 把tar目錄中的所有壓縮包的檔名,儲存到tar.log檔案中。
# 單>是覆蓋。
# 而且tar.log中內容是每一個檔名是一行。
ls *.tar.gz>tar.log
# 把tar目錄中.tgz型別的壓縮包的名字也追加到tar.log檔案中。
# 雙>>是追加。
ls *.tgz>>tar.log &>/dev/null
# 提示:用上面的方式,把需要解壓的所有型別的壓縮檔案的名稱,都存入到tar.log檔案中。

# wc -l命令統計行號,也就是獲取檔案個數。
num=$(cat /tmp/sh/tar/tar.log | wc -l) #或者:wc -l /tmp/sh/tar/tar.log

# 開始遍歷解壓檔案
for((i=1;i<="$num";i=i+1))
    do
        # 用awk命令提取檔名,來獲取解壓檔案的檔名
        # NR是awk的內建變數,表示當前awk所處理的行,是總資料的第幾行。
        # 注意'$i'這個地方,依然要使用單引號,使用雙引號會報錯。
        # awk 'NR=='$i' {print $1} 意思是獲取第幾行的第幾列資訊。
        filename=$(cat tar.log | awk 'NR=='$i' {print $1})

        # 解壓檔案
        tar -zxvf $filename -C /tmp/sh/tar
    done

# 刪除臨時檔案tar.log
rm -rf /tmp/sh/tar/tar.log

總結:

for迴圈的第一種方式,適合作為Shell指令碼的編寫,更為簡單。

相關文章