更多的結構化命令(第十三章)

1. for命令 shell

    for命令的基本格式bash

for VAR in LIST    #VAR爲變量,LIST爲指定隊列
do
    COMMAND        #當VAR存在時執行COMMAND
done

1.1 讀取列表中的值app

[root@localhost test]# vi test.sh                
#!/bin/bash
#Basic for command
#
for test1 in Alabama Alaska Arizona Arkansas California Colorado
do
        echo The states is $test1
done
~                                                                                                      
~                                                                                                      
~                                                                                                                                                                                                           
~                                                                                                      
"test.sh" 7L, 133C written
[root@localhost test]# ./test.sh 
The states is Alabama
The states is Alaska
The states is Arizona
The states is Arkansas
The states is California
The states is Colorado

從上述示例中可看出for命令會遍歷list值列表,並且for循環執行完成後會將變量保持在循環的最後一個值。以下:ide

[root@localhost test]# vi test1.sh
#!/bin/bash
#Basic for command
#
for test1 in Alabama Alaska Arizona Arkansas California Colorado
do
        echo The states is $test1
done
echo the last states is $test1
~                                                                                                      
~                                                                                                                                                                                                           
"test1.sh" 8L, 164C written
[root@localhost test]# ./test1.sh 
The states is Alabama
The states is Alaska
The states is Arizona
The states is Arkansas
The states is California
The states is Colorado
the last states is Colorado


1.2 讀取列表中的複雜值oop

當list中存在單引號等特殊符號時,shell會自動把它當成命令的一部分處理,例如列表中包含 I don't know if this'll work  ,則單引號中的't know if this'會被當成一個賦值來處理,一般有如下兩種解決方法:測試

(1)使用轉移符\將'進行轉移,例如:don\'t;ui

(2)使用""將這個值引發來,例如:"don't"this

[root@localhost test]# vi test2.sh
#!/bin/bash
#another example of how not to use the for command
#
for test2 in I don\'t know if "this'll" work
do      
        echo "word:$test2"
done

~                                                                                                      
~                                                                                                                                                                                                            
~                                                                                                      
"test2.sh" [New] 8L, 139C written
[root@localhost test]# chmod o+x test2.sh
[root@localhost test]# ./test2.sh        
word:I
word:don't
word:know
word:if
word:this'll
word:work

由於for在讀取list中的變量時是已空格爲分割的,若是list中的值包含空格的話,能夠將這個變量用""引發來,這樣for命令在調取變量時就會將包含空格的變量做爲總體調用。server


1.3 從變量中讀取列表排序

for命令的也能夠讀取變量做爲list

[root@localhost test]# vi test3.sh
#!/bin/bash
#
# Using a variable to hold the list
list="Alabama Alaska Arizona Arkansas Colorado"
list=$list" Connecticut"
for state in $list
do
        echo "Have you ever visited $state"
done
~                                                                                                      
~                                                                                                                                                                                                           
~                                                                                                      
"test3.sh" [New] 9L, 187C written
[root@localhost test]# chmod o+x test3.sh
[root@localhost test]# ./test3.sh 
Have you ever visited Alabama
Have you ever visited Alaska
Have you ever visited Arizona
Have you ever visited Arkansas
Have you ever visited Colorado
Have you ever visited Connecticut


1.4 for命令從命令執行結果中讀取變量值

[root@localhost test]# vi test4.sh
#!/bin/bash
#reading values from a file
#
file="states"                                    #將命令參數賦值給變量file
for states in $(cat $file)                       #使用命令替換
do
        echo "Visit beautiful $states"

done
~                                                                                                      
~                                                                                                                                                                                                            
~                                                                                                      
"test4.sh" 9L, 124C written
[root@localhost test]# cat states                #執行shell腳本中相同命令
labama
Alaska
Arizona
Arkansas
Colorado
Connecticut
Delaware
Florida
Georgia
[root@localhost test]# ./test4.sh                #執行腳本,腳本將命令執行結果做爲list賦值給變量
Visit beautiful labama
Visit beautiful Alaska
Visit beautiful Arizona
Visit beautiful Arkansas
Visit beautiful Colorado
Visit beautiful Connecticut
Visit beautiful Delaware
Visit beautiful Florida
Visit beautiful Georgia

for命令支持文件中的內容做爲list,可是在變量賦值時需輸入文件的絕對路徑


1.5 更改字段分隔符

for命令中的list分隔符是經過環境便令IFS來決定的,經過支持:

(1)空格

(2)製表符

(3)換行符

咱們能夠在shell中經過修改IFS變量值來臨時變動分隔符,例如在shell中設定 IFS=$'\n',表示將分隔符設置爲換行符。這樣shell腳本中就能夠使用含有空格的詞了。

[root@localhost test]# vi test4.sh 
IFS.OLD=$IFS
#!/bin/bash
#reading values from a file
#
file="states"
IFS=$'\n'                                    #設置IFS爲換行符
for states in $(cat $file)
do
        echo "Visit beautiful $states"

done
~                                                                                                                                                                                                           
~                                                                                                      
"test4.sh" 10L, 134C written
[root@localhost test]# vi states             #在每一個states上加上一個空格
labam a
Alask a
Arizon a
Arkansa s
Colorad o
Connecticu t
Delawar e
Florid a
Georgi a
~                                                                                                      
~                                                                                                      
~                                                                                                                                                                                                            
"states" 9L, 86C written
[root@localhost test]# cat states 
labam a
Alask a
Arizon a
Arkansa s
Colorad o
Connecticu t
Delawar e
Florid a
Georgi a
[root@localhost test]# ./test4.sh        #執行結果依然正常
Visit beautiful labam a
Visit beautiful Alask a
Visit beautiful Arizon a
Visit beautiful Arkansa s
Visit beautiful Colorad o
Visit beautiful Connecticu t
Visit beautiful Delawar e
Visit beautiful Florid a
Visit beautiful Georgi a


有時候咱們須要臨時修改IFS值,當執行完指定命令後IFS變量恢復默認值,經過使用以下方式:

IFS.OLD=$IFS
IFS=$'\n'
在變量中使用新的IFS值
IFS=$IFS.OLD

咱們還能夠根據實際狀況來指定其餘分割符,例如在/etc/passwd文件中分割符是:,咱們能夠將全部會用到的分隔符串起來便可:

IFS=$'\n':;"

上述能夠將換行符、冒號、分號和雙引號做爲分隔符.


1.6 使用通配符讀取目錄

當使用for命令遍歷目錄中的文件時能夠使用通配符

[root@localhost test]# vi test5.sh       
#!/bin/bash
#iterate through all the files in a directory
#
for file in /root/*
do
        if [ -d $file ]
        then
                echo $file is a directory
        elif [ -f $file ]
        then
                echo $file is a file
        fi
done
~                                                                                                                                                                                                           
~                                                                                                      
"test5.sh" 13L, 191C written
[root@localhost test]# ./test5.sh 
/root/anaconda-ks.cfg is a file
/root/Desktop is a directory
/root/Documents is a directory
/root/Downloads is a directory
/root/initial-setup-ks.cfg is a file
/root/Music is a directory
/root/Pictures is a directory
/root/Public is a directory
/root/shadow is a file
/root/Templates is a directory
/root/test is a directory
/root/Videos is a directory


2. C語言風格的for命令

在C語言中一般用for命令的迭代特性作一個計數器,shell一樣支持這個功能。

2.1 C語言的for命令

格式:for (( variable assignment(變量分配) ; condition(條件) ; iteration process(迭代方式) ))

例如:for (( a=1;a<10;a++))

[root@localhost test]# vi test6.sh
#!/bin/bash
#
for (( a=1;a<10;a++ ))
do
        echo $a
done
~                                                                                                                                                                                                           
~                                                                                                      
"test6.sh" 6L, 54C written
[root@localhost test]# ./test6.sh
1
2
3
4
5
6
7
8
9


2.2 在C語言風格的for命令中可以使用多個變量

[root@localhost test]# vi test7.sh
#!/bin/bash
#
for ((a=1,b=10;a<=10;a++,b--))
do
        echo $a-$b
done
~                                                                                                      
~                                                                                                                                                                                                            
~                                                                                                      
"test7.sh" 6L, 65C written
[root@localhost test]# ./test7.sh
1-10
2-9
3-8
4-7
5-6
6-5
7-4
8-3
9-2
10-1


3. while命令

while命令相似於if-then 和for命令的雜合體,當while中的定義的測試命令返回的值爲0,則while命令會一直運行,直至測試命令返回值不爲0時終止。

3.1 while命令基本格式

格式:

while TEST COMMAND
do
    COMMAND
done

示例:

[root@localhost test]# vi test8.sh
#!/bin/bash
#while command test
#
var=10
while [ $var -ge 0 ]
do
        echo $var
        var=$[ $var - 1 ]
done
~                                                                                                      
~                                                                                                                                                                                                           
~                                                                                                      
"test8.sh" 9L, 100C written
[root@localhost test]# ./test8.sh
10
9
8
7
6
5
4
3
2
1
0


3.2 使用多個測試命令

特色:

(1)while能夠執行多個測試命令

(2)while循環是否終止已while後最後一條命令的執行結果爲準

(3)while的每條測試命令應獨佔一行

示例:

[root@localhost test]# vi test9.sh
#!/bin/bash
#testing a multicommand while loop
#
var=10
while echo $var
        [ $var -ge 0 ]
do
        echo "This is inside the loop"
        var=$[ $var-1 ]
done
~                                                                                                      
~                                                                                                      
~                                                                                                                                                                                                                                                                                                              
"test9.sh" 10L, 145C written
[root@localhost test]# ./test9.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


4.until命令

until命令與while命令相反,當測試命令退出狀態碼返回值不爲0時,bash shell纔會執行循環中的命令。當測試命令退出狀態碼返回值爲0時,則結束循環。

4.1 until命令格式

until TEST COMMAND
do
    COMMAND
done

示例:

[root@localhost test]# vi test10.sh       
#!/bin/bash
#Testing until command
var1=10
until [ $var1 -eq 0 ]
do
        echo var1 is $var1
        var1=$[ $var1 - 1 ]
done
~                                                                                                      
~                                                                                                                                                                                                           
~                                                                                                      
"test10.sh" 8L, 114C written
[root@localhost test]# ./test10.sh
var1 is 10
var1 is 9
var1 is 8
var1 is 7
var1 is 6
var1 is 5
var1 is 4
var1 is 3
var1 is 2
var1 is 1


5.嵌套循環

特色:嵌套循環輸出將已嵌套的循環的次方

示例:

[root@localhost test]# vi test11.sh
#!/bin/bash
#nesting for loops
for ((a=1;a<=3;a++))
do
        echo "starting loop:$a"
        for ((b=1;b<=3;b++))
        do
                echo "inside loop:$b"
        done
done
~                                                                                                      ~                                                                                                      
"test11.sh" 10L, 141C written
[root@localhost test]# ./test11.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

混用效果也同樣

while和for混用示例:

[root@localhost test]# vi test12.sh
#!/bin/bash
#while and for
#
var=5
while [ $var -ge 0 ]
do
        echo "outer loop:$var"
        for ((a=1;a<=3;a++))
        do
                echo "inside loop:$a"
        done
        var=$[ $var - 1 ]
done    
~                                                                                                      
~                                                                                                                                                                                                            
"test12.sh" [New] 13L, 163C written
[root@localhost test]# ./test12.sh
outer loop:5
inside loop:1
inside loop:2
inside loop:3
outer loop:4
inside loop:1
inside loop:2
inside loop:3
outer loop:3
inside loop:1
inside loop:2
inside loop:3
outer loop:2
inside loop:1
inside loop:2
inside loop:3
outer loop:1
inside loop:1
inside loop:2
inside loop:3
outer loop:0
inside loop:1
inside loop:2
inside loop:3

until命令和while命令混用

[root@localhost test]# vi test13.sh
#!/bin/bash
# using until and while loops

var1=3

until [ $var1 -eq 0 ]
do
        echo "Outer loop: $var1"
        var2=1
        while [ $var2 -lt 5 ]
        do
                var3=$(echo "scale=4; $var1 / $var2" | bc)
                echo " Inner loop: $var1 / $var2 = $var3"
                var2=$[ $var2 + 1 ]
        done
        var1=$[ $var1 - 1 ]
done
~                                                                                                      
~                                                                                                                                                                                                           
"test13.sh" 17L, 280C written
[root@localhost test]# ./test13.sh
Outer loop: 3
 Inner loop: 3 / 1 = 3.0000
 Inner loop: 3 / 2 = 1.5000
 Inner loop: 3 / 3 = 1.0000
 Inner loop: 3 / 4 = .7500
Outer loop: 2
 Inner loop: 2 / 1 = 2.0000
 Inner loop: 2 / 2 = 1.0000
 Inner loop: 2 / 3 = .6666
 Inner loop: 2 / 4 = .5000
Outer loop: 1
 Inner loop: 1 / 1 = 1.0000
 Inner loop: 1 / 2 = .5000
 Inner loop: 1 / 3 = .3333
 Inner loop: 1 / 4 = .2500


6. 控制循環

6.1 break命令

break命令能夠退出任意類型的循環

6.1.1 跳出單個循環

[root@localhost test]# vi test14.sh
#!/bin/bash
#Testing break
#
for var1 in 1 2 3 4 5 6 7 8 9 10
do
        if [ $var1 -eq 5 ]
        then
                break
        fi
        echo $var1
done
echo "The for loop is completed"

~                                                                                                                                                                                                                                           
~                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
~                                                                                                                                                                                                                                           
"test14.sh" 13L, 154C written
[root@localhost test]# ./test14.sh
1
2
3
4
The for loop is completed


6.1.2 跳出內部循環

示例:

[root@localhost test]# vi test15.sh
#!/bin/bash
#Testing break
#
for (( a=1; a<4; a++ ))
do
        echo "outer loop: $a"
        for (( b=1; b<100; b++ ))
        do
                if [ $b -eq 5 ]
                then
                        break
                fi
                echo "inner loop: $b"
        done
done
~                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
~                                                                                                                                                                                                                                           
"test15.sh" 15L, 184C written
[root@localhost test]# ./test15.sh
outer loop: 1
inner loop: 1
inner loop: 2
inner loop: 3
inner loop: 4
outer loop: 2
inner loop: 1
inner loop: 2
inner loop: 3
inner loop: 4
outer loop: 3
inner loop: 1
inner loop: 2
inner loop: 3
inner loop: 4


6.1.3 跳出外部循環

[root@localhost test]# vi test16.sh
#!/bin/bash
#breaking out of an outer loop
#
for (( a=1; a<4; a++ ))
do
        echo "outer loop: $a"
        for (( b=1; b< 100; b++ ))
        do
                if [ $b -eq 5 ]
                then
                        break 2
                fi
                echo "inner loop: $b"
        done
done
~                                                                                                                                                                                                                                           
~                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
~                                                                                                                                                                                                                                           
"test16.sh" 15L, 203C written
[root@localhost test]# ./test16.sh
outer loop: 1
inner loop: 1
inner loop: 2
inner loop: 3
inner loop: 4


6.2 continue命令

特色:

(1)continue命令能夠終止符合指定條件的循環,可是不會退出循環;

(2)當continue執行後,該循環中continue後面的命令將不會被執行;

(3)continue有跟break同樣的特性,能夠支持跳出多級循環,僅須要使用continue N,N指明循環數,默認爲1.

continue常規示例:

[root@localhost test]# vi test17.sh
#!/bin/bash
#Testing continue command
#
for (( var1=1; var1<15; var1++ ))
do
        if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
        then
                continue
        fi
        echo "var1 is $var1"
done
~                                                                                                      
~                                                                                                                                                                                                           
~                                                                                                      
"test17.sh" [New] 11L, 165C written
[root@localhost test]# chmod o+x test17.sh
[root@localhost test]# ./test17.sh
var1 is 1
var1 is 2
var1 is 3
var1 is 4
var1 is 5
var1 is 10
var1 is 11
var1 is 12
var1 is 13
var1 is 14


當continue執行後,該循環中continue後面的命令將不會被執行

[root@localhost test]# vi test.sh 
#!/bin/bash
#improperly using the continue commmand in a while loop
var1=0
while echo "while iteration: $var1"
        [ $var1 -lt 15 ]
do
        if [ $var1 -gt 5 ] && [ $var1 -lt 10 ]
        then
                continue
        fi
        echo " inside iteration number :$var1 "
        var1=$[ $var1 + 1 ]
done
~                                                                                                      
~                                                                                                                                                                                                           
~                                                                                                      
"test.sh" 13L, 260C written
[root@localhost test]# ./test.sh |more
while iteration: 0
 inside iteration number :0 
while iteration: 1
 inside iteration number :1 
while iteration: 2
 inside iteration number :2 
while iteration: 3
 inside iteration number :3 
while iteration: 4
 inside iteration number :4 
while iteration: 5
 inside iteration number :5 
while iteration: 6
while iteration: 6
while iteration: 6
while iteration: 6
while iteration: 6
while iteration: 6
while iteration: 6
while iteration: 6


continue有跟break同樣的特性,能夠支持跳出多級循環,僅須要使用continue N,N指明循環數,默認爲1.

[root@localhost test]# vi test1.sh
#!/bin/bash
#continuing an outer loop
for (( a=1; a<5; a++ ))
do
        echo "iteration $a:"
        for (( b=1; b<3; b++ ))
        do
                if [ $a -gt 2 ] && [ $a -lt 4 ]
                then
                        continue 2
                fi
                var3=$[ $a * $b ]
                echo "The result of $a * $b is $var3"
        done
done
~                                                                                                      
~                                                                                                                                                                                                           
"test1.sh" 15L, 247C written
[root@localhost test]# ./test1.sh
iteration 1:
The result of 1 * 1 is 1
The result of 1 * 2 is 2
iteration 2:
The result of 2 * 1 is 2
The result of 2 * 2 is 4
iteration 3:
iteration 4:
The result of 4 * 1 is 4
The result of 4 * 2 is 8


7. 處理循環的輸出

能夠經過在done後重定向文件,將執行結果輸出給指定文件

示例:

[root@localhost test]# vi test2.sh
#!/bin/bash
#Testing output to file
#
for file in /etc/*
do
        if [ -d "$file" ]
        then
                echo "$file is a directory"
        else
                echo "$file is a file"
        fi
done > /root/test/output              #將結果輸出至output文件
~                                                                                                      
~                                                                                                                                                                                                            
"test2.sh" 12L, 175C written
[root@localhost test]# ./test2.sh
[root@localhost test]# cat output
/etc/abrt is a directory
/etc/adjtime is a file
/etc/aliases is a file
/etc/aliases.db is a file
/etc/alsa is a directory
/etc/alternatives is a directory
/etc/anacrontab is a file
/etc/asound.conf is a file
/etc/at.deny is a file
/etc/at-spi2 is a directory
/etc/audisp is a directory
/etc/audit is a directory
/etc/avahi is a directory
/etc/bash_completion.d is a directory
/etc/bashrc is a file
/etc/binfmt.d is a directory
/etc/brltty is a directory
/etc/brltty.conf is a file


也能夠將結果經過管道符| 做爲參數輸入給命令

示例:

[root@localhost test]# vi test3.sh
#!/bin/bash
#
#piping a loop to another command
#
for state in "North Dakota" Connecticut Illinois Alabama Tennessee
do 
        echo "$state is the next place to go"
done | sort                     #將輸出結果使用sort進行排序
echo "This completes our travels"
~                                                                                                      
~                                                                                                      
~                                                                                                                                                                                                         
"test3.sh" [New] 8L, 204C written
[root@localhost test]# chmod o+x test3.sh
[root@localhost test]# ./test3.sh
Alabama is the next place to go
Connecticut is the next place to go
Illinois is the next place to go
North Dakota is the next place to go
Tennessee is the next place to go
This completes our travels


8. 循環實例

8.1 在環境變量的目錄中查找可執行文件

[root@localhost test]# vi test.sh
#!/bin/bash
#
IFS=:
for directory in $PATH
do
        echo "$directory:"
        for file in $directory/*
        do
                if [ -x $file ]
                then
                        echo "$file"
                fi
        done
done
~                                                                                                      
~                                                                                                                                                                                                           
~                                                                                                      
"test.sh" 14L, 153C written
[root@localhost test]# ./test.sh |more
/usr/local/sbin:
/usr/local/bin:
/usr/sbin:
/usr/sbin/abrt-auto-reporting
/usr/sbin/abrt-configuration
/usr/sbin/abrtd
/usr/sbin/abrt-dbus
/usr/sbin/abrt-harvest-pstoreoops
/usr/sbin/abrt-harvest-vmcore
/usr/sbin/abrt-install-ccpp-hook
/usr/sbin/abrt-server
/usr/sbin/accept
/usr/sbin/accessdb
/usr/sbin/accton
/usr/sbin/addgnupghome
/usr/sbin/addpart
/usr/sbin/adduser
/usr/sbin/agetty
/usr/sbin/alsactl
/usr/sbin/alsa-info
/usr/sbin/alsa-info.sh
/usr/sbin/alternatives
/usr/sbin/anaconda
/usr/sbin/anacron
/usr/sbin/applygnupgdefaults
/usr/sbin/arp
/usr/sbin/arpd
/usr/sbin/arping
/usr/sbin/atd
/usr/sbin/atrun
--More--


8.2 使用腳本批量建立用戶

[root@localhost test]# vi test.sh 
#!/bin/bash
#process new user accounts
#
input="useradd.csv"              #useradd.csv爲當前目錄下建立的csv文件,格式爲userid,name
while IFS=',' read -r userid name  #將分隔符設置爲,使用read -r命令會使讀取一行後自動換行
do
        echo "adding user $name"  #輸出建立信息
        useradd -c $name -m $userid #建立用戶
done < $input                       
~                                                                                                                                                                                                           
~                                                                                                      
"test.sh" 9L, 167C written
[root@localhost test]# ./test.sh
adding user 2000
adding user 2001
[root@localhost test]# cat useradd.csv 
test1,2000
test2,2001
相關文章
相關標籤/搜索