第13章: 更多的結(jié)構(gòu)化命令

[TOC]


1. for命令

bash shell提供了for命令,允許你創(chuàng)建一個遍歷一系列值的循環(huán)。每次迭代都使用其中一個值來執(zhí)行已定義好的一組命令。下面是bash shell中for命令的基本格式。

for var in list
do
    commands
done

在list參數(shù)中,你需要提供迭代中要用到的一系列值。在每次迭代中,變量var會包含列表中的當前值。在do和done語句之間輸入的命令可以是一條或多條標準的bash shell命令。在這些命令中,$var變量包含著這次迭代對應(yīng)的當前列表項中的值。

1.1 讀取列表中的值

for命令最基本的用法就是遍歷for命令自身所定義的一些列值。

#!/bin/bash
# Basic for command
for test in Alabama Alaska Arizona
do
    echo "The next state is $test"
done

每次for命令遍歷列表,它都會將列表中的下個值賦給test變量。test變量可以像for命令語句中的其他腳本變量一樣使用。在最后一次迭代后,$test變量的值會在shell腳本的剩余部分一直保持有效。

1.2 讀取列表中的復雜值

1.3 從變量讀取列表

通常shell腳本遇到的情況是,你將一系列值都集中存儲在一個變量中,然后需要遍歷變量中的整個列表。

#!/bin/bash
# Using a variable to hold the list.
list="Alabama Alaska Arizona"
list=$list" Connecticut"
for state in $list
do
    echo "Visit $state."
done

./test1_3.sh
Visit Alabama.
Visit Alaska.
Visit Arizona.
Visit Connecticut.

$list中包含了用于迭代的標準文本值列表。

1.4 從命令讀取值

生成列表中值的另一個途徑就是使用命令的輸出??梢杂妹钐鎿Q來執(zhí)行任何能產(chǎn)生輸出的命令,然后在for命令中使用該命令的輸出。

#!/bin/bash
# Reading values from a file.
#
file="states.txt"
IFS=$'\n'
for state in $(cat $file)
do
    echo "Visit $state."
done

./test1_4.sh
Visit Alabama.
Visit Alaska.
Visit New York.
Visit North Carolina.

這個例子中使用了cat命令來輸出文件states.txt中的內(nèi)容。

1.5 更改字段分隔符

IFS(internal field separator)叫作內(nèi)部字段分隔符,IFS環(huán)境變量定義了bash shell用作字段分隔符的一系列字符。默認情況下,bash shell會將下列字符當作字段分隔符:

  • 空格
  • 制表符
  • 換行符

如果bash shell在數(shù)據(jù)中看到了這些字符中的任意一個,它就會假定這表明了列表中一個新數(shù)據(jù)字段的開始。在處理可能包含有空格的數(shù)據(jù)時,這會比較麻煩。要解決這個問題,可以在shell腳本中臨時更改IFS環(huán)境變量的值來限制被bash shell當作字段分隔符的字符。例如,如果你想修改IFS的值,使其只能識別換行符,那就必須這么做:

IFS=$'\n'

將這個語句加入到腳本中,告訴bash shell在數(shù)據(jù)值中忽略空格和制表符。

#!/bin/bash
# Reading values from a file.
#
file="states.txt"
IFS=$'\n'
for state in $(cat $file)
do
    echo "Visit $state"
done

cat states.txt
Alabama
Alaska
New York
North Carolina

./test1_5.sh
Visit Alabama
Visit Alaska
Visit New York
Visit North Carolina

1.6 用通配符讀取目錄

可以使用for命令來自動遍歷目錄中的文件。進行此操作時,必須在文件名或文件路徑名中使用通配符。它會強制shell使用文件擴展匹配。文件擴展匹配是生成匹配指定通配符的文件名或路徑名的過程。

#!/bin/bash
# Itrate through all the files in a directory.
#
for file in /home/henryhu/bash-study/*
do
    if [ -d "$file" ]
    then
        echo "$file is a directory."
    elif [ -f "$file" ]
    then
        echo "$file is a file."
    fi
done

for命令會遍歷/home/henryhu/bash-study/*輸出的結(jié)果。該代碼用test命令測試了每個條目(使用方括號方法),以查看它是目錄(通過-d參數(shù))還是文件(通過-f參數(shù))。在Linux中,目錄名和文件名中包含空格當然是合法的。為了適應(yīng)這種情況,應(yīng)該將$file變量用雙引號圈起來。

2. C語言風格的for命令

C語言風格的for命令看起來如下:

for ((a = 1; a < 10; a++ ))

注意,有些部分并沒有遵循bash shell標準的for命令:

  • 變量賦值可以有空格;
  • 條件中的變量不以美元符開頭;
  • 迭代過程的算式未用expr命令格式。
#!/bin/bash
# Testing the C-Style for loop
#
for (( i = 1; i <= 10; i++ ))
do
    echo "The next number is $i."
done

for循環(huán)通過定義好的變量(本例中是變量i)來迭代執(zhí)行這些命令。在每次迭代中,$i變量包含了for循環(huán)中賦予的值。在每次迭代后,循環(huán)的迭代過程會作用在變量上。

3. while命令

while命令某種意義上是if-then語句和for循環(huán)的混雜體。while命令允許定義一個要測試的命令,然后循環(huán)執(zhí)行一組命令,只要定義的測試命令返回的是退出狀態(tài)碼0。它會在每次迭代的一開始測試test命令。在test命令返回非零退出狀態(tài)碼時,while命令會停止執(zhí)行那組命令。

3.1 while基本格式

while命令的格式是:

while test command
do
    other commands
done

while命令中定義的test command和if-then語句中的格式一模一樣??梢允褂萌魏纹胀ǖ腷ash shell命令,或者用test命令進行條件測試,比如測試變量值。

while命令的關(guān)鍵在于所指定的test command的退出狀態(tài)碼必須隨著循環(huán)中運行的命令而改變。如果退出狀態(tài)碼不發(fā)生變化,while循環(huán)就將一直不停地進行下去。

#!/bin/bash
# While command test
#
var1=10
while [ $var1 -gt 0 ]
do
    echo $var1
    var1=$[ $var1 - 1 ]
done

./test3_1.sh
10
9
8
7
6
5
4
3
2
1

while命令定義了每次迭代時檢查的測試條件:

while [ $var1 -gt 0 ]

只要測試條件成立,while命令就會不停地循環(huán)執(zhí)行定義好的命令。在這些命令中,測試條件中用到的變量必須修改,否則就會陷入無限循環(huán)。

3.2 使用多個測試命令

while命令允許你在while語句行定義多個測試命令。只有最后一個測試命令的退出狀態(tài)碼會被用來決定什么時候結(jié)束循環(huán)。

#!/bin/bash
# Testing a multicommand while loop
#
var1=10
while echo $var1
    [ $var1 -ge 0 ]
do
    echo "This is inside the loop."
    var1=$[ $var1 -1 ]
done

./test3_2.sh
10
This is inside the loop.
9
This is inside the loop.
8
This is inside the loop.
7
This is inside the loop.
6
This is inside the loop.
5
This is inside the loop.
4
This is inside the loop.
3
This is inside the loop.
2
This is inside the loop.
1
This is inside the loop.
0
This is inside the loop.
-1

while語句中定義了兩個測試命令。

while echo $var1
    [ $var1 -ge 0 ]

第一個測試簡單地顯示了var1變量的當前值。第二個測試用方括號來判斷var1變量的值。在循環(huán)內(nèi)部,echo語句會顯示一條簡單的消息,說明循環(huán)被執(zhí)行了。while循環(huán)會在var1變量等于0時執(zhí)行echo語句,然后將var1變量的值減一。接下來再次執(zhí)行測試命令,用于下一次迭代。echo測試命令被執(zhí)行并顯示了var變量的值。直到shell執(zhí)行test測試命令,while循環(huán)才會停止。

4. until命令

until命令和while命令的工作方式完全相反。until命令要求指定一個通常返回非零退出狀態(tài)碼的測試命令。只有測試命令的退出狀態(tài)碼不為0,bash shell才會執(zhí)行循環(huán)中列出的命令。一旦測試命令返回了退出狀態(tài)碼0,循環(huán)就結(jié)束了。until命令的格式如下:

until test commands
do
    other commands
done

和while命令類似,可以在until命令語句中放入多個測試命令。只有最后一個命令的退出狀態(tài)碼覺定了bash shell是否執(zhí)行已定義的other commands。

#!/bin/bash
# Using the until command
#
var1=100
until [ $var1 -eq 0 ]
do
    echo $var1
    var1=$[ $var1 - 25 ]
done

本例中會測試var1變量來決定until循環(huán)何時停止。只要該變量的值等于0,until命令就會停止循環(huán)。

5. 嵌套循環(huán)

循環(huán)語句可以在循環(huán)內(nèi)使用任意類型的命令,包括其他循環(huán)命令。這種循環(huán)叫作嵌套循環(huán)(nested loop)。

#!/bin/bash
# Test nested loop
#
for ((a = 1; a <=3;a++ ))
do
    echo "Starting loop $a:"
    for(( b = 1; b <= 3; b++))
    do
        echo " Inside loop:$b"
    done
done

 ./test5_1.sh
Starting loop 1:
 Inside loop:1
 Inside loop:2
 Inside loop:3
Starting loop 2:
 Inside loop:1
 Inside loop:2
 Inside loop:3
Starting loop 3:
 Inside loop:1
 Inside loop:2
 Inside loop:3

被嵌套的循環(huán)(也稱為內(nèi)部循環(huán),inner loop)會在外部循環(huán)的每次迭代中遍歷一次它所有的值。

6. 處理循環(huán)的輸出

在shell腳本中,可以對循環(huán)的輸出使用管道或進行重定向。這可以通過在done命令之后添加一個處理命令來實現(xiàn)。

#!/bin/bash
# Redirecting the for output to a file
#
for ((a = 1; a < 10 ; a++ ))
do
    echo "The number is $a."
done > test.txt
echo "The command is finished."

 cat test.txt
The number is 1.
The number is 2.
The number is 3.
The number is 4.
The number is 5.
The number is 6.
The number is 7.
The number is 8.
The number is 9.

shell創(chuàng)建了test.txt文件并將for命令的輸出重定向到這個文件。shell在for命令之后正常顯示了echo語句。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容