Linux 之Shell for循環


@代表所有參數
所以如果后面跟上echo $v你會發現他會一次顯示user userdebug eng
$poo -le ${#prodlist[@]} 
這句話是說 $poo小於等於prodlist中的所有的值
是這個意思嗎?

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

[zhangqi@localhost shellscript]$ sh for_ex9.sh

盡管可以使用多個變量,但你只能在for循環中定義一種條件。

#!/bin/bash
for ((a=1,b=10;a<=10;a++,b--))
do
echo "$a - $b"
done

執行結果:

1 - 10
使用類C風格for循環要注意以下事項:
a.如果循環條件最初的退出狀態為非0,則不會執行循環體
b.當執行更新語句時,如果循環條件的退出狀態永遠為0,則for循環將永遠執行下去,從而產生死循環
c.Linux shell中不運行使用非整數類型的數作為循環變量
d.如果循環體中的循環條件被忽略,則默認的退出狀態為0
e.在類C風格的for循環中,可以將三個語句全部忽略掉,下面是合法的for循環

for((; ; ))
do
echo "hello world"
done
---------------------

第一類:數字性循環-->seq在in后面的應用

#!/bin/bash
#也是產生等差數列-->默認是1
for i in $(seq 1 10) #產生的是一個字符串,默認IFS是以空格隔開!
do
echo $(expr $i \* 3 + 1); #主要是復習:expr乘法的特殊用法!-->空格隔開
done
補充:產生[1,10]的自然數-->{}在in后面的應用

total=0 #全局變量
for i in {1..100} #".."表示連續,默認也是IFS為空格隔開
do
((total+=i))
done
echo -e "total is:${total}"

#多行注釋
<<COMMENR
for i in mysql_{0,1,4,12}sql #多個文件
do
echo $i
samtools view -c $i
done
COMMENT
第二類:字符性循環

最原始的

#!/bin/bash
#使用列表for循環顯示周一到周日對應的英文-->學習日期的英文
for day in Monday Tuesday Wednesday Thursday Friday Saturday Sunday
do
echo "$day"
done
變量的類型

#!/bin/bash
list="Linux Java C++ Python"
for i in $list
do
echo -e "Language is ${i}"
done
cat在in后面的應用-->逐行讀取文件的內容(默認是IFS),所以不是逐行打印!

#!/bin/bash
for i in $(cat 日志顏色.sh) #注意:pwd當前目錄下的文件
do
echo $i
done
思考:如果想逐行原樣輸出!

#!/bin/bash
# reading content from a file
file="日志文件.sh"
#將這個語句加入到腳本中,告訴bash shell在數據值中忽略空格和制表,使其只能識別換行符!
IFS=$'\n'
for std in $(cat $file)
do
echo "$std"
done
說明:IFS的一些說明!

bash shell會將下列字符當作字段分隔符:空格、制表符、換行符

說明:如果在shell在數據中看到這些字符中的任意一個,它就會假定這表明了列表中一個新數據字段的開始!
參考的最佳安全實踐:在改變IFS之前保存原來的IFS值,之后再恢復它。

保證了:在腳本的后續操作中使用的是IFS的默認值

實現:

IFS.OLD=$IFS #默認的IFS的數值-->也是環境變量!
IFS=$'\n' #自定義的IFS數值
<在代碼中使用新的IFS值> #待使用自定義IFS的部分!
IFS=$IFS.OLD #恢復默認的IFS
第三類:路徑查找

ls在in后面的命令是-->讀取當前pwd下的文件(廣義上)!

#!/bin/bash
for i in `ls`; #ls可以結合統配符應用!
do
echo $i is file name\! ; #注意:\的應用!
done
 用通配符讀取目錄(無命令)

for file in ~/*; #一級目錄下的內容-->並不遞歸顯示!
do
echo $file is file path \! ; #${file}代表的是文件的全路徑
done
通過腳本傳參

#!/bin/bash
#回憶1:統計腳本參數的個數
echo "argument number are $#"!
#回憶2:參數的內容-->此處可以換成$@來測試!
echo "the input is $*"
#循環執行
for argument in "$*";
do
echo "$argument "
done
IFS:內部字段分隔符

需求如下:

#遍歷一個文件中用冒號分隔的值:-->特殊文件-->/etc/passwd文件等!
IFS=:
#如果要指定多個IFS字符,只要將它們在賦值行串起來就行。
IFS=$'\n':;"
總結:

#(1)從變量讀取列表
# 將一系列的值都集中存儲在一個變量中,然后需要遍歷變量中的整個列表

#(2)從命令讀取值
#有兩種方式可以將命令輸出賦值給變量:
# (1)反引號字符(`)
# (2)$()格式
補充:在列表構成上分多種情景,如數字列表、字符串列表、命令列表、腳本傳參列表等!



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM