上次已經(jīng)學(xué)習(xí)了基礎(chǔ)的結(jié)構(gòu)化命令if語句,循環(huán)語句也是使用頻率非常高的結(jié)構(gòu)化命令,比如for語句、while語句等。一起來學(xué)習(xí)吧~
要點(diǎn)一、for命令
1、基礎(chǔ)格式
#!/bin/bash
for test in one two three four five
do
echo the number is $test
done
如上關(guān)于for語句的格式:
-
test為變量; -
in后面的系列值為list參數(shù),以空格隔開,變量依次迭代;
在循環(huán)結(jié)束后,$test變量會(huì)在腳本中保持最后一個(gè)值(five)。當(dāng)然,除非你修改了它。
- 在 do 和 done 之間為一/多條標(biāo)準(zhǔn)的bash shell命令;
- 關(guān)于寫法,for 與 do 可以放在一行里,用分號(hào)
;隔開。如下
for test in one two three four five; do
echo the number is $test
done
2、關(guān)于list參數(shù)
上述舉的例子應(yīng)該是最簡(jiǎn)單的形式:用空格分隔的文本字符串。針對(duì)更加實(shí)用的情況,list參數(shù)也可以是以下的形式
2.1、儲(chǔ)存變量讀取
#!/bin/bash
list="one two three four five"
for test in $list
do
echo the number is $test
done
- 如上代碼,將系列值儲(chǔ)存在list變量里,供test迭代。
2.2、文本文件/命令替換讀取
cat number.txt
one
two
three
four
five
- 如上,使用
cat命令準(zhǔn)備文本文件
#!/bin/bash
file="number.txt" #將文件引入腳本里的變量
for test in $(cat $file)
do
echo the number is $test
done
- 使用命令替換符
$( )讀取
2.3、字段分隔符
內(nèi)部字段分隔符(internal field separator)環(huán)境變量為IFS,其默認(rèn)的分隔符有空格、制表符、換行符。所以上述例子中有采用空格分隔的;有采用換行符分隔的。
- 但是可能會(huì)遇到以下情況:
(1)每行文本里有空格符,但只想根據(jù)換行符分隔,需要重新定義默認(rèn)分隔符。
cat number1.txt
one two
three
four
five six
#!/bin/bash
IFS=$'\n' #設(shè)定分隔符僅為換行符,忽略空格
file="number1.txt"
for test in $(cat $file)
do
echo the number is $test
done
針對(duì)上述情況,可以將含有空格的行文字加上雙引號(hào),而不用修改IFS。這種解決辦法也適用于文本中本身含有引號(hào)的干擾情況。
(2)在腳本里修改環(huán)境變量IFS僅會(huì)在腳本中生效,不影響外部環(huán)境。如果在一個(gè)腳本中需要在一處更改默認(rèn)分隔符,而后續(xù)需要沿用原來的默認(rèn)設(shè)置。
IFS.OLD=$IFS
IFS=$'\n'
#
#
#
IFS=$IFS.OLD
(3)在某種情況下,需要指定多個(gè)新的分隔符
IFS=$'\n':;"
- 上述代碼分別指定換行符、冒號(hào)、分號(hào),雙引號(hào)作為字段分隔符。
此外關(guān)于list參數(shù),還有一個(gè)技巧:通配符。比如
for file in /home/li/l*代碼能夠遍歷/home/li/目錄中所有以l開頭的對(duì)象。
3、C語言風(fēng)格的for命令
#!/bin/bash
for (( a = 1; a < 10; a++ ))
do
echo the number is $a
done
記住第一行特殊格式,賦值可以有空格,條件中的變量不是以美元符開頭。
- 第一部分為原始值;
- 第二部分為循環(huán)條件;
- 第三部分為迭代過程(遞增/遞減)。
要點(diǎn)二、while命令
#!/bin/bash
var1=10
while [ $var1 -gt 0 ]
do
echo $var1
var1=$[ $var1 - 1 ]
done
關(guān)于while語句的注意點(diǎn)有:
- while后面的語句判斷后面的命令是命令退出狀態(tài)碼,若返回0(成功執(zhí)行),則繼續(xù)do的命令;
- do后面的命令一般包括兩部分。一是執(zhí)行目標(biāo)命令(循環(huán)的最終目的)
echo $var1、二是迭代變量值,var1=$[ $var1 - 1 ]再次返回給while 進(jìn)行判斷。直到while后的退出狀態(tài)碼不為0 - done 標(biāo)志循環(huán)語句結(jié)束。
- 值得注意的是在 while后可執(zhí)行目標(biāo)命令,但我覺得應(yīng)該不常見。
此外還有until語句,與while相反就不探究了(詳見p272)
要點(diǎn)三、嵌套循環(huán)
嵌套循環(huán)就是在迭代中再使用迭代,命令的執(zhí)行次數(shù)為乘積關(guān)系。下面以兩個(gè)簡(jiǎn)單例子了解一下~
for嵌套for
#!/bin/bash
for (( a = 1; a < 3; a++ ))
echo "Outer loop $a :"
for (( b = 1; b <= 3; b++ ))
do
echo " Inside loop: $b"
done
done
while嵌套for
#!/bin/bash
#
var1=5
#
while [ $var1 -ge 0 ]
do
echo "Outer loop: $var1"
for (( var2 = 1; var2 < 3; var2++ ))
do
var3=$[ $var1*$var2 ]
echo " Inner loop: $var1 * $var2 = $var3"
done
var1=$[ $var1 - 1 ] #在最后交代while變量的迭代
done
要點(diǎn)四、控制循環(huán)
在循環(huán)條件下,有時(shí)并非list參數(shù)所舉的全部系列值都想采用,也存在只取部分值的情況。此時(shí)需要使用控制循環(huán)命令,一般搭配if語句,表明終止循環(huán)的條件。(我覺得也可以直接修改list參數(shù)的值。針對(duì)具體情況,怎么方便怎么來吧。)
break命令
一旦執(zhí)行,直接終止退出,不在考慮后面的list參數(shù)。
#!/bin/bash
for var1 in 1 2 3 4 5 6 7 8 9
do
if [ $var1 -eq 5 ]
then
break
fi
echo "Iteration number: $var1"
done
echo "The for loop is completed"
上述代碼結(jié)果中,var1會(huì)變到4;到5時(shí),因滿足if條件,執(zhí)行break命令而終止循環(huán)
continue命令
- 不會(huì)直接完全終止,可以設(shè)置終止的list參數(shù)范圍
#!/bin/bash
for (( var1 = 1; var1 < 15; var1++ ))
do
if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
then
continue
fi
echo "Iteration number: $var1"
done
- var1值為1時(shí),退出碼不為0;不執(zhí)行then的continue命令,往下執(zhí)行echo語句;
- 若為6,則執(zhí)行then語句,跳過這一圈剩余的循環(huán)命令,繼續(xù)下一個(gè)for取值7;
- 取到10時(shí),退出碼不為0;不執(zhí)行then的continue命令,往下執(zhí)行echo語句。
關(guān)于循環(huán)控制,也可在嵌套循環(huán)里執(zhí)行
break或continue。因?yàn)樯婕暗絻?nèi)循環(huán)、外循環(huán),以及控制命令加不加參數(shù)的變化,不在贅述了,詳見p277。
最后以一個(gè)實(shí)例結(jié)束
- 目的:在PATH環(huán)境變量中,查找系統(tǒng)有哪些可執(zhí)行文件可供使用。
#!/bin/bash
IFS=:
for folder in $PATH
do
echo "$folder:"
for file in $folder/*
do
if [ -x $file ]
then
echo " $file"
fi
done
done
./test.sh | more
補(bǔ)充一個(gè)知識(shí)點(diǎn):在shell腳本中,可以對(duì)循環(huán)的輸出使用管道或進(jìn)行重定向;直接在done 命令后添加相關(guān)命令即可。如下:
done > output.txt
done | sort
參考教材為《Linux命令行與shell腳本編程大全》