647 瀏覽數

Bash Shell Script – for 迴圈

for 迴圈的使用有好幾種方式,先來看第一種

for var in list

語法如下

for var in list
do
     statements
done

直接來看下面的範例,定義了一個變數 testlist 字串,內容為 test1 test2 ,接下來的 for 的變數 test 會取用這兩個字串,並執行 do done 內的程式.

[root@localhost ~]$ vi for.sh
#!/bin/bash
testlist="test1 test2"
for test in $testlist
do
  echo Testlist=$test
done

省掉變數,直接把 list 寫在 for 後面也是一樣的.

#!/bin/bash
for test in test1 test2
do
  echo Testlist=$test
done

結果如預期的列印出變數 testlist 內的字串.

[root@localhost ~]$ chmod a+x for.sh
[root@localhost ~]$ ./for.sh
Testlist=test1
Testlist=test2

for var in $(seq minnum maxnum)

語法如下

for var in $(seq minnum maxnum)
do
     statements
done

下面這個範例可以用來測試目前所處環境,哪一些 IP 已經是電腦使用了 (鳥哥網站的範例).

[root@localhost ~]$ vi ping.sh
#!/bin/bash
network="172.16.15"
for ip in $(seq 1 10)
do
        ping -c 1 -w 1 ${network}.${ip} &> /dev/null && result=0 || result=1
        if [ "${result}" == 0 ]; then
                echo "This IP ${network}.${ip} is unavailable."
        else
                echo "This IP ${network}.${ip} is available."
        fi
done

程式碼說明:

network="172.16.15"

定義了一個變數 network 字串,內容為我目前網段的位址.

for ip in $(seq 1 10)

這邊的 for 寫法比較特殊 $(seq 1 10) 表示 ip 變數得值會從 1 , 2 , 3 到 10 才會結束.

ping -c 1 -w 1 ${network}.${ip} &> /dev/null && result=0 || result=1

ping 一個封包 (-c 1) , 等待回應時間為一秒 (-w 1)
&> (等同 2>&1 ) 標準輸出 (stdout)+標準錯誤輸出 (stderr) ,把執行結果內容導向至 /dev/null (空裝置,也就是不會把結果顯示在標準輸出)

&& || 的用法
當執行指令時都會回傳一個執行後的代碼給變數 $?,成功的執行完指令後會回傳一個 0 值(有錯誤時會回傳 錯誤代碼).
利用 ping 的指令來看看 變數 $? 的變化.

root@ubuntu:~# ping -c 1 -w 1 192.8.1.1
PING 192.8.1.1 (192.8.1.1) 56(84) bytes of data.

--- 192.8.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 999ms

root@ubuntu:~# echo $?
1
root@ubuntu:~# ping -c 1 -w 1 172.16.15.130
PING 172.16.15.130 (172.16.15.130) 56(84) bytes of data.
64 bytes from 172.16.15.130: icmp_seq=1 ttl=64 time=0.050 ms

--- 172.16.15.130 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.050/0.050/0.050/0.000 ms
root@ubuntu:~# echo $?
0

cmd1 && cmd2 若 cmd1 執行正確且無錯誤 ($?=0),則執行 cmd2 ,反之若 cmd1 執行完畢且為錯誤 ($?≠0),則 cmd2 不執行.
cmd1 || cmd2 若 cmd1 執行正確且無錯誤 ($?=0),則 cmd2 不執行 ,反之若 cmd1 執行完畢且為錯誤 ($?≠0),則開始執行 cmd2.
簡化一下剛剛的指令
ping && result=0 || result=1
ping 成功後 ($?=0) result=0,因為 $?=0 所以後半段 || 就不會去執行了.
ping 失敗後 ($?≠0) ,不執行 result=0,因為 $?≠0 所以後半段 || 就會去執行 result=1 了.

do
        if [ "${result}" == 0 ]; then
                echo "This IP ${network}.${ip} is unavailable."
        else
                echo "This IP ${network}.${ip} is available."
        fi
done

for 的迴圈,如果 result 變數被設定為 0 ($?=0),則 顯示該 IP 已經有人使用.反之顯示該 IP 沒有人使用.

執行結果:

root@ubuntu:~# chmod a+x ping.sh
root@ubuntu:~# ./ping.sh 
This IP 172.16.15.1 is unavailable.
This IP 172.16.15.2 is unavailable.
This IP 172.16.15.3 is available.
This IP 172.16.15.4 is available.
This IP 172.16.15.5 is available.
This IP 172.16.15.6 is available.
This IP 172.16.15.7 is available.
This IP 172.16.15.8 is available.
This IP 172.16.15.9 is available.
This IP 172.16.15.10 is available.

for (( EXP1; EXP2; EXP3 ))

這語法與 C 語言類似,語法如下:

for (( EXP1; EXP2; EXP3 ))
do
     statements
done

EXP1 : 初始值
EXP2 : 限制值
EXP3 : 累進值

把剛剛 ping 的範例修改成這個語法如下:

[root@localhost ~]$ vi ping.sh
#!/bin/bash
network="172.16.15"
for ((ip=1;ip<=10;ip=ip+1))
do
        ping -c 1 -w 1 ${network}.${ip} &> /dev/null && result=0 || result=1
        if [ "${result}" == 0 ]; then
                echo "This IP ${network}.${ip} is unavailable."
        else
                echo "This IP ${network}.${ip} is available."
        fi
done

ip=ip+1 可以簡寫成為 ip++

#!/bin/bash
network="172.16.15"
for ((ip=1;ip<=10;ip++))
do
        ping -c 1 -w 1 ${network}.${ip} &> /dev/null && result=0 || result=1
        if [ "${result}" == 0 ]; then
                echo "This IP ${network}.${ip} is unavailable."
        else
                echo "This IP ${network}.${ip} is available."
        fi
done

發表迴響