Shell编程中循环命令用于特定条件下决定某些语句重复执行的控制方式,有三种经常使用的循环语句:for、while和until。while循环和for循环属于“当型循环”,而until属于“直到型循环”。循环控制符:break和continue控制流程转向。html
while循环用于不断执行一系列命令,也用于从输入文件中读取数据,其格式为:shell
//while 命令 do 命令1 命令2 . . . done
虽然一般只使用一个命令,但在 while和do之间能够放几个命令。命令一般用做测试条
件。
只有当命令的退出状态为 0时,do和done之间命令才被执行,若是退出状态不是 0,则循
环终止。
命令执行完毕,控制返回循环顶部,从头开始直至测试条件为假。express
实例编程
#!/bin/bash # Program: # This program will show the use of if # History: # 2015/1/8 Alex First release i=10 while [[ $i -gt 5 ]] do echo $i i=`expr $i - 1`; done exit 0
注意:在Shell中四则运算不能简简单单的加减乘除,应该要写以下的格式: val1=`$val2 - 1` 其中“=”后面用“`”包住表达式,这个符号在Shell中十分有用,是Tab键上面“~”的原来形式。能够用来将不少命令的结果保存到一个变量中去。接着就是运算符了,运算符的左右两边必须是空格,不然会出错。
deyuy/bin/my_shell >> ./while1.sh 10 9 8 7 6
注意: 1.expr命令的用法请参考 http://blog.chinaunix.net/uid-25880122-id-2937521.html 2.``的做用是运行``之间的命令,而且将命令运行的结果返回。详细请参考:http://blog.csdn.net/miyatang/article/details/8077123 3. 更多while实例参考:http://blog.csdn.net/firefoxbug/article/details/7237319
until循环执行一系列命令直至条件为真时中止。 until循环与while循环在处理方式上恰好相反。通常while循环优于until循环,但在某些时候—也只是极少数状况下, until循环更加有用。vim
//until循环格式为: until 条件 命令1 . . . done
条件可为任意测试条件,测试发生在循环末尾,所以循环至少执行一次—请注意这一
点。bash
until循环中,只要条件不为真,就执行do和done之间的循环命令,或者说,在until循环中,一直执行do和done之间的循环命令,直到条件为真;服务器
–避免生成死循环。 app
# Program: # This program will show the use of until # History: # 2015/1/13 Alex First release sum=0 num=10 until test $num -eq 0 do sum=`expr $sum + $num` num=`expr $num - 1` done echo "sum = $sum" exit 0 deyuy/bin/my_shell >> sh until.sh sum = 55
//for循环通常格式为: for 变量名i n列表 do 命令1 命令2… done
当变量值在列表里, for循环即执行一次全部命令,使用变量名访问列表中取值。命令可为任何有效的shell命令和语句。
变量名为任何单词。 in列表用法是可选的,若是不用它, for循环使用命令行的位置参数。
in列表能够包含替换、字符串和文件名,列表能够自定义,也能够经过命令返回值生成,下面是一些经常使用例子。oop
#!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/12 First release # 自定义列表 for loop in 1 2 3 4 5 do echo "loop=$loop" done exit 0 deyuy/bin/my_shell >> chmod u+x for1.sh deyuy/bin/my_shell >> ./for1.sh loop=1 loop=2 loop=3 loop=4 loop=5 //还能够经过读取文件内容生成变量列表 deyuy/bin/my_shell >> vim num.txt 1 2 3 4 5 6 7 8 #!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/12 First release # 以命令返回值做为列表 i=0 for i in `cat num.txt` do echo "i=$i" done exit 0 deyuy/bin/my_shell >> ./for1.sh i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8
#!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/12 First release # 自定义列表:带引号 i=0 for loop in "apple hhhh bbbb eeee" do i=`expr $i + 1` echo "loop=$loop" echo "count=$i" done exit 0 deyuy/bin/my_shell >> chmod u+x for4.sh deyuy/bin/my_shell >> ./for4.sh loop=apple hhhh bbbb eeee count=1 *说明:从结果能够看出for循环打印字符串到结束,包括空格,只执行了一次。若是把 in列表改成 for loop in "apple" "hhhh" "bbbb" "eeee" 则输出结果为 loop=apple count=1 loop=hhhh count=2 loop=bbbb count=3 loop=eeee count=4
#!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/12 First release # 自定义列表,不带引号 i=0 for loop in apple hhhh bbbb eeeedo i=`expr $i + 1` echo "loop=$loop" echo "count=$i" done exit 0 deyuy/bin/my_shell >> ./for4.sh loop=apple count=1 loop=hhhh count=2 loop=bbbb count=3 loop=eeee count=4
注意:对比两张方式输出的不一样能够看出,若是用户想让把空格分割的每一个单词都输出要经过第二种方式。测试
# Program: # This program will show the use of for # History: # 2015/1/12 First release for loop in `ls` do echo "$loop" done exit 0 deyuy/bin/my_shell >> sh for2.sh app1 for1.sh for2.sh fun1.sh hello.sh hh.sh if.sh if2.sh test.sh test2.sh var.sh while1.sh
#!/bin/bash # Program: # This program will show the use of for # 统计当前目录下文件数 # History: # 2015/1/12 First release counter=0 for files in * do counter=`expr $counter + 1` done echo "There are $counter files in `pwd` directory." exit 0 deyuy/bin/my_shell >> sh for3.sh There are 13 files in /home/deyuy/bin/my_shell directory.
#!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/13 release i=0 for params do i=`expr $i + 1` echo "You supplied $params as a command line option" echo "count=$i" done echo $params exit 0 deyuy/bin/my_shell >> ./for5.sh p1 p2 p3 You supplied p1 as a command line option count=1 You supplied p2 as a command line option count=2 You supplied p3 as a command line option count=3 p3 ###下面的脚本包含i n"$ @",结果与上面的脚本相同。 #!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/13 release i=0 for params in "$@" do i=`expr $i + 1` echo "You supplied $params as a command line option" echo "count=$i" done echo $params exit 0 deyuy/bin/my_shell >> ./for5.sh p1 p2 p3 You supplied p1 as a command line option count=1 You supplied p2 as a command line option count=2 You supplied p3 as a command line option count=3 p3 ###下面的脚本包含i n"$ *",结果与上面的脚本不一样。 #!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/13 release i=0 for params in "$*" do i=`expr $i + 1` echo "You supplied $params as a command line option" echo "count=$i" done echo $params exit 0 deyuy/bin/my_shell >> ./for5.sh p1 p2 p3 You supplied p1 p2 p3 as a command line option count=1 p1 p2 p3
说明:关于$@和$*的区别请参考http://www.cnblogs.com/yuexiaxiaoxi/articles/4203609.html
嵌入循环能够将一个f o r循环嵌在另外一个f o r循环内:
for 变量名1 in列表1 do for 变量名2 in 列表2 do 命令1 . . . done done
下面脚本即为嵌入for循环,这里有两个列表apps和scripts。第一个包含服务器上应用
的路径,第二个为运行在每一个应用上的管理脚本。对列表 apps上的每个应用,列表
scripts里的脚本将被运行,脚本实际上为后台运行。脚本使用tee命令在登陆文件上放一条
目,所以输出到屏幕的同时也输出到一个文件。查看输出结果就能够看出嵌入for循环怎样使
用列表scripts以执行列表apps上的处理。
#!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/13 release APPS="/apps/accts /apps/claims /apps/stock /apps/serv" SCRIPTS="audit.check report.run cleanup" MY_DATE=`date +%H:%M" on "%d/%m/%Y` i=0 j=0 #outer loop for loop in $APPS do i=`expr $i + 1` #inner loop for loop2 in $SCRIPTS do j=`expr $i + 1` echo "system $loop now running $loop2 at $MY_DATE" echo "inner loop counter=$j" done echo "outer loop counter=$i" done echo $params deyuy/bin/my_shell >> ./for6.sh system /apps/accts now running audit.check at 20:53 on 12/01/2015 inner loop counter=2 system /apps/accts now running report.run at 20:53 on 12/01/2015 inner loop counter=2 system /apps/accts now running cleanup at 20:53 on 12/01/2015 inner loop counter=2 outer loop counter=1 system /apps/claims now running audit.check at 20:53 on 12/01/2015 inner loop counter=3 system /apps/claims now running report.run at 20:53 on 12/01/2015 inner loop counter=3 system /apps/claims now running cleanup at 20:53 on 12/01/2015 inner loop counter=3 outer loop counter=2 system /apps/stock now running audit.check at 20:53 on 12/01/2015 inner loop counter=4 system /apps/stock now running report.run at 20:53 on 12/01/2015 inner loop counter=4 system /apps/stock now running cleanup at 20:53 on 12/01/2015 inner loop counter=4 outer loop counter=3 system /apps/serv now running audit.check at 20:53 on 12/01/2015 inner loop counter=5 system /apps/serv now running report.run at 20:53 on 12/01/2015 inner loop counter=5 system /apps/serv now running cleanup at 20:53 on 12/01/2015 inner loop counter=5 outer loop counter=4
case语句为多选择语句。能够用 case语句匹配一个值与一个模式,若是匹配成功,执行相
匹配的命令。case语句格式以下:
case expression in pattern1 ) statements ;; pattern2 ) statements ;; ... esac
case工做方式如上所示。取值后面必须为单词 i n,每一模式必须以右括号结束。取值能够
为变量或常数。匹配发现取值符合某一模式后,其间全部命令开始执行直至;;。
取值将检测匹配的每个模式。一旦模式匹配,则执行完匹配模式相应命令后再也不继续
其余模式。若是无一匹配模式,使用星号 *捕获该值,再接受其余输入。
模式部分可能包括元字符,与在命令行文件扩展名例子中使用过的匹配模式类型相同,
即:
* 任意字符。
? 任意单字符。
[..] 类或范围中任意字符。
注意:
1.模式字符串中可使用通配符
2.若是一个模式字符串中包含多个模式,那么各模式之间应以竖线(|)隔开,表各模式是“或”的关系,即只要给定字符串与其中一个模式相配,就会执行其后的命令列表。
3.各模式字符串应是惟一的,不该重复出现,而且要合理安排它们的出现顺序,例如,不该将“*”做为头一个模式字符串,由于“*”能够与任何字符串匹配,若第一个出现,就不会再检查其余模式了。
4.case语句以关键字case开头,以关键字esac结束。
5.case的退出(返回)值是整个结构中最后执行的命令的退出值。若没有执行任何命令,则退出值为0.
#!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/13 First release case $1 in y|Y) echo "your choice is yes";; n|N) echo "your choice is no";; *) echo "your choice is others";; esac exit 0 deyuy/bin/my_shell >> chmod u+x case.sh deyuy/bin/my_shell >> ./case.sh y your choice is yes deyuy/bin/my_shell >> ./case.sh n your choice is no deyuy/bin/my_shell >> ./case.sh jjjj your choice is others
格式:
select 变量 in 列表 do 命令行(一般用到循环变量) done
制做一个选择表,在列表中选择一个选项执行命令行。若是选择的变量不在列表序列中,则返回一个空值。须要用break退出循环。
#!/bin/bash # Program: # This program will show the use of for # History: # 2015/1/13 First release echo "a is 5 ,b is 3. Please select your method: " a=5 b=3 select var in "a+b" "a-b" "a*b" "a/b" do break done case $var in "a+b") echo 'a+b= '`expr $a + $b`;; "a-b") echo 'a-b= '`expr $a - $b`;; "a*b") echo 'a*b= '`expr $a \* $b`;; "a/b") echo 'a/b= '`expr $a / $b`;; *) echo "input error" esac deyuy/bin/my_shell >> chmod u+x select.sh deyuy/bin/my_shell >> ./select.sh a is 5 ,b is 3. Please select your method: 1) a+b 2) a-b 3) a*b 4) a/b #? 3 a*b= 15
–一、break:用于当即终止当前循环的执行,break命令可使用户从循环体中退出来。
–语法:break[n] ,其中,n表示要跳出几层循环,默认值为1
#!/bin/bash for var1 in 1 2 3 do for var2 in 0 5 do if [ $var1 -eq 2 -a $var2 -eq 0 ] then break 2 else echo "$var1 $var2" fi done done
运行结果:
1 0
1 5
–二、continue:跳过循环体中在其以后的语句,会返回到本循环层的开头,进行下一次循环。
–语法:continue[n],其中,n表示从包含continue语句的最内层循环体向外跳到第几层循环,默认值为1,循环层数是由内向外编号。
#!/bin/bash NUMS="1 2 3 4 5 6 7" for NUM in $NUMS do Q=`expr $NUM % 2` if [ $Q -eq 0 ] then echo "Number is an even number!!" continue fi echo "Found odd number" done
运行结果:
Found odd number Number is an even number!! Found odd number Number is an even number!! Found odd number Number is an even number!! Found odd number