參考文章 – https://devhints.io/bash#loops
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 minimum maximum)
語法如下:
for var in $(seq minimum maximum) 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),則開始執行 cmd3.
簡化一下剛剛的指令
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 var in {minimum..maximum}
這個語法功能同上的語法.
for var in {minimum..maximum} do statements done
把剛剛 ping 的範例修改成這個語法如下:
#!/bin/bash network="172.16.15" for ip in {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
for var in {minimum..maximum..step}
語法如下,與上面相比多了 step (等差)的設定:
for var in {minimum..maximum..step} do statements done
把剛剛 ping 的範例修改成這個語法如下:
#!/bin/bash network="172.16.15" for ip in {1..10..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
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