『忘了再學』Shell流程式控制制 — 36、for循環介紹

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腳本的編寫,更為簡單。