购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.4 循环结构

循环结构可以使Shell程序重复地执行一系列命令列表,而决定命令列表是否继续循环执行的条件是一个命令的返回值。test命令常常被用来控制一个循环是否继续。与分支语句不同的是,在分支语句中,开始分支语句的关键字和结束分支语句的关键字是相反的(如if与fi、case与esac),循环结构由一个关键字和一些条件开始,整个循环体用关键字do和done包围起来。

2.4.1 for语句

Shell程序中的for语句用来对参数列表中的每一个条目都顺序执行一次命令列表,每完成一次循环,就将列表中下一个条目的值赋给变量,直到完成最后一个条目的循环为止。for语句的一般格式如下:

在for循环语句中,关键字为for、in、do和done。变量的赋值会贯穿for循环的执行过程,参数列表是一串由空格或者Tab健分割开的字符串组成的,在每一次循环执行中都要将一个字符串赋值给变量。for循环的执行过程如下:

(1)Shell变量被赋值为参数列表中的第一个字符串(参数1);

(2)执行由do和done包围起来的一系列命令列表;

(3)Shell变量被赋值为参数列表中的下一个字符串(参数2);

(4)执行由do和done包围起来的一系列命令列表;

……

(5)Shell变量被赋值为参数列表中的最后一个字符串(参数n);

(6)执行由do和done包围起来的一系列命令列表;

(7)循环结束。

【程序2.7】求整数1~5的平方数:power.sh。

使用chmod命令修改文件的执行权限:

运行程序,输出结果如下:

使用Shell的通配符或者变量替换,可以很轻松地生成参数列表。例如,查询当前目录下的所有文件是否为普通文件,如果为普通文件,则列出各个文件的详细信息,代码如程序2.8所示。

【程序2.8】测试文件类型并打印文件的属性信息:file_test.sh。

使用chmod命令修改文件的执行权限:

运行程序,输出结果如下:

Shell的for语句也可以不带参数列表,并省略关键字in,格式如下:

这样,Shell会自动将命令行输入的所有参数依次组织成列表。事实上,这和下面的情况是完全一样的:

2.4.2 while语句

Shell程序的第二种循环语句是while语句,该语句在判断条件为真时重复地执行一段代码(命令列表)。while语句的一般格式如下:

先判断条件表达式的布尔值,判断其退出状态是否为0,如果为0,就执行do和done之间的代码段;然后再次判断条件表达式的退出状态是否为0,如果为0,则再次执行do和done之间的代码段;该过程一直循环下去,直到条件表达式的退出状态不为0为止。此时退出循环程序,继续执行done后面的代码段。

当然,如果第一次判断条件表达式的退出状态就不为0,那么do和done之间的代码段根本就不会执行,而直接跳到done后面的代码执行。

程序2.9首先添加一个新的用户组newgroup(groupadd命令),然后使用while循环自动添加属于这个组的30个用户,用户名的形式为“stdxx”,其中xx为01~30。代码如程序2.9所示。

【程序2.9】为系统添加新的用户组和该用户组下的用户:add_user.sh。

while循环的条件为变量i的值小于等于30,在循环体内对变量i值进行加1操作,当i值大于30时结束循环。需要提醒读者注意的是,由于该Shell程序会修改系统中的用户数量,所以只有具有超级用户权限才能执行该程序,在运行程序前可使用su命令将系统切换至超级用户。su命令的用法很简单,直接在命令行下输入:

运行程序后,系统会添加一个新的用户组newgroup,并在该用户组下添加30个普通用户stu01……stu30,而且可以看到在 /home目录下也新增了30个用户子文件夹。

此外,while循环语句(包括后面将要讲到的until语句)通常和shift命令结合使用,以处理命令行中输入的参数个数可变的情况。使用shift命令可以依次移动命令行参数的位置,即$2->$1,$3->$2……而移位之前的前一个位置参数在移位后将自动消失。每进行一次移位,$#自动减1。

使用shift命令的另一个原因是,Bourne Shell的位置参数变量为$1~$9,因此通过位置变量最多只能访问9个参数。但这并不等于在命令行上最多只能输入9个参数,此时如果想访问多于9个的参数,就必须使用shift命令。

另外,shift命令后可加整数参数进行一次多个移位,如shift 3,表示一次移动3个位置的参数。

程序2.10是演示使用while语句结合shift命令计算命令行上输入的所有整数之和的例子。

【程序2.10】求命令行上的所有整数之和:shift_sum.sh。

使用chmod命令修改文件的执行权限:

运行程序,输出结果如下:

2.4.3 until语句

只要while后面的命令退出状态为0,while循环就一直执行下去。until命令与while命令的功能类似,唯一的区别在于,只要until后面的命令退出状态不为0,until循环就一直执行下去。也就是说,使用until语句重复执行一段代码直到条件为真为止。与while语句类似,until语句的一般格式如下:

使用until语句重写程序2.10,修改如下:

可以看到,只需将条件判断中的整数操作符不等于“-ne”修改为等于“-eq”,将while关键字替换为until,就可实现相同的功能。

2.4.4 异常退出循环

在很多情况下,可能需要在循环的正常终止条件满足之前放弃一个循环的执行。break和continue命令提供了一种无条件的流程控制,通常用于在遇到一个错误的情况下终止当前的循环。而exit命令则用于不能从某种情况下恢复出来而又必须终止整个程序运行的时候。

break命令会终止循环并且将控制权传递到done关键字后面的第一个命令,结果是完全跳出这个循环体而继续执行下面的命令。

continue命令有一点不同,当在程序执行过程中遇到该命令时,会忽略本次循环中剩余的命令,而将控制权交给循环的顶部。这样,continue命令能让程序仅仅终止所有循环中的一个循环过程而继续从当前循环的顶部开始执行。在while和until循环中,这种处理会导致在初始列表的开始部分继续执行,在for循环中,会将变量设置为列表中的下一个条目,然后继续执行循环。

exit命令停止执行当前的Shell程序,并且根据提供的参数为这个Shell程序设置一个返回值,如果没有提供返回值参数,则当前Shell程序的返回值会被设置为在exit命令之前执行的那条命令的返回值。

需要说明的是,循环的流程控制在正常情况下应当是通过设置循环开始部分的条件(针对while、until循环),或者是列表中的条目全部循环完毕(针对for循环)的情况来结束循环。而对循环过程进行中断操作只是在循环执行期间遇到没有规律的或是错误的条件时才应当使用。

另外,在Shell编程中有时要用到无限循环的技巧,也就是说这种循环一直执行,直到遇到break或continue命令。这种无限循环通常是使用true或false命令开始的。UNIX系统中的true总是返回0值,而false则返回非0值。

程序2.11演示了Shell死循环的使用方法,通过选择不同的选项,可以对文件执行不同的操作(作为示例,这里仅列举了创建、删除文件,退出交互式程序,读者可试着添加其他更复杂的操作选项),以及在死循环中使用continue退出当前循环,使用break退出整个循环体,使用exit退出程序,等等。代码如程序2.11所示。

【程序2.11】Shell循环及异常退出循环演示:cycle_test.sh。

使用chmod命令修改文件的执行权限:

运行程序,输出结果如下(↙代表回车):

由于while循环的test条件始终为真(true),所以整个程序运行后将会是一个无限的死循环,除非循环体中的某些命令能终止循环的运行(这就是break命令所做的事情)。

在字符命令行的交互选项中,用户输入1表示新建一个文件,接着提示用户输入文件名,然后判断文件是否存在,若存在则使用continue退出本次循环;若不存在则创建该文件。用户输入2表示删除一个文件,接着提示用户输入将要删除的文件名,然后判断文件是否存在并且是否为一个普通文件,若满足条件则删除该文件;若不满足,则提示用户出错信息,并使用continue退出本次循环。用户输入3表示退出应用程序,之后提示用户是否确定退出,若用户输入Yes,则使用break退出死循环(进而退出程序);若用户输入No,则使用continue退出本次循环,继续后面的死循环。 zwOSQXqr4gS5GxtDC1v03jS3VDOgnfjMAEBq80kH6qKs6mfOEur8jVOFPNgFzllD

点击中间区域
呼出菜单
上一章
目录
下一章
×