1. 程式人生 > >Linux Shell系列教程(十三)之Shell for迴圈

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