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