shell编程中for/while/util/case/select/break/continue

原创
2016/07/08 10:33
阅读数 236

Shell编程中循环命令用于特定条件下决定某些语句重复执行的控制方式,有三种常用的循环语句:for、while和until。while循环和for循环属于“当型循环”,而until属于“直到型循环”。循环控制符:break和continue控制流程转向。

一、while语句结构

while循环用于不断执行一系列命令,也用于从输入文件中读取数据,其格式为:

//while 命令
do
命令1
命令2
. . .
done


虽然通常只使用一个命令,但在 while和do之间可以放几个命令。命令通常用作测试条
件。
只有当命令的退出状态为 0时,do和done之间命令才被执行,如果退出状态不是 0,则循
环终止。
命令执行完毕,控制返回循环顶部,从头开始直至测试条件为假。

实例

#!/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循环执行一系列命令直至条件为真时停止。 until循环与while循环在处理方式上刚好相反。一般while循环优于until循环,但在某些时候—也只是极少数情况下, until循环更加有用。

//until循环格式为:
until 条件
命令1
. . .
done


条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次—请注意这一
点。

until循环中,只要条件不为真,就执行do和done之间的循环命令,或者说,在until循环中,一直执行do和done之间的循环命令,直到条件为真;

–避免生成死循环。 

# 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循环一般格式为:
for 变量名i n列表
do
命令1
命令2…
done

当变量值在列表里, for循环即执行一次所有命令,使用变量名访问列表中取值。命令可为任何有效的shell命令和语句。
变量名为任何单词。 in列表用法是可选的,如果不用它, for循环使用命令行的位置参数。
in列表可以包含替换、字符串和文件名,列表可以自定义,也可以通过命令返回值生成,下面是一些常用例子。

1) 整数列表  

#!/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

 

2) 字符串列表

#!/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

注意:对比两张方式输出的不同可以看出,如果用户想让把空格分割的每个单词都输出要通过第二种方式。

3) 打印当前目录下所有文件

# 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

4) 循环计数

#!/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.

5) 使用位置参数

#!/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

6)循环嵌套

嵌入循环可以将一个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语句格式如下:

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结构

格式:

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和continue

–1、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

 

–2、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
展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部