Linux Shell系列教程(十三)之Shell for迴圈
13.1、Shell for迴圈語法
for 變數 in 列表
do
command1
command2
...
commandN
done
**也可以寫成:for var in list; do
- 13.1.1、讀取列表中的值
#!/bin/bash
#basic for command
for test in Alabama BOb Tom Console
do
echo The next state is $test
done
執行結果:
The next state is Alabama
The next state is BOb
The next state is Tom
The next state is Console
在最後一次迭代後,$test變數的值會在shell指令碼的剩餘部分保持有效。它會一直保持最後一次迭代的值(除非你修改了它)。
- 13.1.2、讀取列表中的複雜值
有兩種解決辦法:
*使用轉義字元(反斜線)來將單引號轉移;
*使用雙引號來定義用到單引號的值。
#!/bin/bash
#basic for command
for test in I don\'t think if "this'll" work
do
echo The next state is $test
done
執行結果:
The next state is I
The next state is don't
The next state is think
The next state is if
The next state is this'll
The next state is work
*記住,for命令用空格來劃分列表中的每個值。如果在單獨的資料值中有空格,就必須用雙引號將這些值圈起來。
-
13.1.3、從變數讀取列表
將一系列的值都集中儲存在一個變數中,然後需要遍歷變數中的整個列表。
#!/bin/bash
#using a variable to hold the list
list="Alabama BOb Tom Console"
#向已有列表中新增或拼接一個值
list=$list" success"
for state in $list
do
echo "this word is $state"
done
執行結果:
this word is Alabama
this word is BOb
this word is Tom
this word is Console
this word is success
-
-
13.1.4、從命令讀取值
有兩種方式可以將命令輸出賦值給變數:
(1)反引號字元(`)
(2)$()格式
例如:
test=`date`
test=$(date)
生成列表中所需值就是使用命令的輸出。
#!/bin/bash
# reading values from a file
file="states"
#for state in `ps -ef | grep 'tomcat.8701' | awk '{print $2}'`
for state in $(cat $file)
do
echo "visit beautiful $state"
done
states檔案內容;
Alabama BOb
Tom Console
執行結果:
visit beautiful Alabama
visit beautiful BOb
visit beautiful Tom
visit beautiful Console
- 13.1.5、更改欄位分隔符
造成這個問題的原因是特殊的環境變數IFS,叫作內部欄位分隔符。預設情況下,bash shell會將下列字元當作欄位分隔符:
*空格
*製表符
*換行符
如果bash shell在資料中看到這些字元中的任意一個,它就會假定這表明了列表中一個新資料欄位的開始。
想修改IFS的值,使其只能識別換行符,那就必須:
IFS=$'\n'
將這個語句加入到指令碼中,告訴bash shell在資料值中忽略空格和製表符。
#!/bin/bash
# reading values from a file
file="states"
IFS=$'\n'
for state in $(cat $file)
do
echo "visit beautiful $state"
done
執行結果:
visit beautiful Alabama BOb
visit beautiful Tom Console
一個可參考的安全實踐是在改變IFS之前儲存原來的IFS值,之後再恢復它。
實現:
IFS.OLD=$IFS
IFS=$'\n'
<在程式碼中使用新的IFS值>
IFS=$IFS.OLD
這就保證了在指令碼的後續操作中使用的是IFS的預設值。
遍歷一個檔案中用冒號分隔的值:
IFS=:
如果要指定多個IFS字元,只要將它們在賦值行串起來就行。
IFS=$'\n':;"
這個賦值會將換行符、冒號、分號和雙引號作為欄位分隔符。如何使用IFS字元解析資料沒有任何限制。
13.1.6、用萬用字元讀取目錄
for file in /proc/*;
do
echo $file is file path \! ;
done
- 13.2、類C風格for迴圈的語法格式
for((expr1; expr2; expr3))
do
command
command
...
done
有些部分並沒有遵循bash shell標準的for命令:
*變數賦值可以有空格
*條件中的變數不以美元符開頭
*迭代過程的算式為用expr命令格式
ex9、輸出前5個正數
#!/bin/bash
#使用類C風格for迴圈輸出1~5
for ((integer = 1; integer <= 5; integer++))
do
echo "$integer"
done
[[email protected] shellscript]$ sh for_ex9.sh
1
2
3
4
5
儘管可以使用多個變數,但你只能在for迴圈中定義一種條件。
#!/bin/bash
for ((a=1,b=10;a<=10;a++,b--))
do
echo "$a - $b"
done
執行結果:
1 - 10
2 - 9
3 - 8
4 - 7
5 - 6
6 - 5
7 - 4
8 - 3
9 - 2
10 - 1
使用類C風格for迴圈要注意以下事項:
a.如果迴圈條件最初的退出狀態為非0,則不會執行迴圈體
b.當執行更新語句時,如果迴圈條件的退出狀態永遠為0,則for迴圈將永遠執行下去,從而產生死迴圈
c.Linux shell中不執行使用非整數型別的數作為迴圈變數
d.如果迴圈體中的迴圈條件被忽略,則預設的退出狀態為0
e.在類C風格的for迴圈中,可以將三個語句全部忽略掉,下面是合法的for迴圈
for((; ; ))
do
echo "hello world"
done