shell编程之循环语句(1)
目标:
完成这一章,你将能够作以下事情:
使用while语句在条件为真的时候重复地执行一段代码。
使用until语句重复执行一段代码直到条件为真。
使用交互性的for语句进行循环控制。
1.循环的简单介绍
目标: 重复的执行一段命令列表。
控制; 基于一个关键命令的返回值。
三种格式: while ... do ... done
until ... do ... done
for ... do ... done
循环语句让你可以重复执行一个命令列表,而决定是继续循环还是跳出循环是基于一个命令的返回值。test命令常常被用来控制一个循环是否继续。
与分支语句不同的是,在分支语句中开始一个分支语句的关键字和结束一个分支语句的关键字是相反的(if/fi 和case/esac),循环语句由一个关键字和一些条件开始,循环体整个用do/done来包围起来。
2.使用let来进行算术计算
语法:
let expression or (( expression ))
例子:
$ x=10 $ x=12
$ y=2 $ let "x <10"
$ let x=x+2 $ echo $?
$ echo $x 1
12 $ (( x > 10 ))
$ let "x = x / (y+1)" $ echo $?
$ echo $x $ 0
4 $ if ((x > 10 ))
$ (( x = x + 1 )) > then echo x greater
$ echo $x > else echo x not greater
5 fi
x greater
循环语句通常使用一个增长的数字变量来进行控制。使用let命令,可以在shell脚本中使用算术表达式。这个命令允许使用长的整数运算。在上例中,expression代表一个shell变量的算术表达式和能够被shell识别的操作符,而(( ))可以替let命令。shell能够识别的表达式如下所示:
操作符 描述
- 减去
! 逻辑相反
* / % 乘,除,余数
+ - 加,减
<= >= < > 关系比较
== != 等于不等于
= 赋值
括号能够被用作改变表达式中计算的顺序,就像在
let "x=x/(y+1)"
中一样
注意双引号被用来忽略括号的特殊含义。同样如果你希望使用空格来分隔操作符和操作符的时候,就必须使用双引号,或者(( ))语句:
let " x = x + (y / 2)" 或者(( x= x+ (y / 2) ))
当使用逻辑和关系操作符,(!,<=,>=,<,>,++,~=),的时候,shell会返回一个代码变量,?会反映结果是真还是假,再一次说明,必须使用双引号来防止shell将大于和小于运算符当作I/O重定向。
3.while语句
重复执行循环体,直到条件为真
语法:
while list A do list B done
例子:
$ cat test_while X=1 while (( X <= 10 )) do echo hello X is $X let X=X+1 done
$ test_while
hello X is 1 hello X is 2 . . . hello X is 10
while语句是shell提供的一种循环机制,当条件为真的时候它允许循环体中的命令(list B)继续执行。条件判断是通过list A中最后一个命令的返回值来进行。通常一个test或者let命令被用作控制循环的执行,但是任何命令都能被用来产生一个返回值。上面的例子中使用的是test命令可以用let命令来代替,如下:
$ X=1 $ while [ $x -le 10 ] > do > echo hello X is $X > let X=X+1 > done
命令执行的过程如下:
1.list A中的命令被执行。
2.如果list A中的最后一个命令的返回值为0(真),执行list B。
3.回到第一步。
4.如果list A中的最后一个命令的返回值不为0(假),跳到下面done关键字后的第一个命令。
提醒:注意while循环会无穷执行下去,因为有一些循环的控制命令的返回值永远为真。
$ cat while_infinite
while true do echo hello done
$ while_infinite
hello hello . . .
ctrl + c
4. while结构举例
例A: 例B
如果ans为yes就重复执行 当有命令行参数时重复执行
ans=yes while (($# != 0 )) while do [ "$ans" = yes ] if test -d $1 do then
echo Enter a name echo contents of $1; read name ls -F $1 echo $name >> file.names fi echo "Continue?" shift echo Enter yes or no echo There are $# items read ans echo left on the cmd line done done
上例是两个while语句的例子,例A提示用户输入,然后对用户的输入进行判断,来决定是否继续执行循环,例子B中,循环会对命令行中每一个参数进行判断,如果参数是一个目录,这个目录中的内容会被显示出来。如果这个参数不是一个目录,程序会跳过。注意shift命令的用法,它允许一个一个存取每一个参数。和while命令一起使用可以使这个循环非常灵活。它不关心参数的个数是1个还是100个,循环会继续执行直到所有的参数都被存取。
注意,如果你希望循环至少执行一次,就必须进行某些设置。例A中会执行循环体至少一次因为ans已经被设为yes。在例B中,如果程序的执行不带任何参数($#等于0),这个循环就一次都不会执行。
5.until语句
重复循环直到条件为真为止。
语法: 例子:
until $ cat test_until list A X=1 do until (( x > 10 )) list B do done echo hello X is $X let X=X+1 done
$ test_until hello X is 1 hello X is 2 hello X is 3 . . .
hello X is 10
until语句是shell提供的另一种循环机制,它会持续执行命令(list B)直到一个条件为真为止。同while循环类似,条件判断由list A中的最后一条命令的返回值来决定的。
命令的执行过程如下:
1.list A中的命令被执行。
2.如果list A中最后一条命令的返回值为非0(假),执行list B。
3.返回到第一步。
4.如果list A中的最后一条命令的返回值为0(真),跳到done关键字后的第一条命令。
注意:until循环的无穷执行下去,因为有些循环语句中的控制语句的返回值始终为假。
$ x=1 $ until > [ $ x -eq 0 ] > do > echo hello > done hello hello hello . . .
ctrl + c
6.until的例子
例A 例B
重复执行循环体直到ans为no为止 重复执行循环直到没有命令行参数为止
ans=yes until (( $# == 0 )) until do [ "$ans" = no ] if test -d $1 do then echo Enter a name echo context of $1; read name ls -F $1 echo $name >> file.names fi echo "Continue?" shift echo Enter yes or no echo There are $# items read ans echo left on the cmd line. done done
上例的结构与while语句中的例子类似,但是使用until语句来。注意在两种语句的test条件的逻辑关系是相反的。
同时请注意用户输入的敏感性由一些轻微的变化。使用while语句,只有用户的输入的字符串为“yes”时循环才会执行,继续执行循环的条件十分严格,使用until语句,循环会在用户使用与no不同的任何字符时都会执行。它对于继续进行循环的条件不太严格,你也许希望在决定那一种结构最符合你的要求的时候考虑这一特征。
预定义ans变量的值不再是必须的,因为它的值会被初始化为NULL,由于NULL不等于no,test会返回假,而循环会被执行。你仅仅需要将$ans用括号引起来,以免在test语句执行时发生语法错误。 |