《UNIX编程环境》——5.3 while和until循环:观察情况

简介: 在第3章中,for循环用于一些简单的迭代程序。一般地,for对一组文件名进行循环,如在for i in .c中;或对shell程序的所有参数进行循环,如for i in $。但实际上,shell中的for循环可以有更大的用途,如在which里的for循环。

本节书摘来自异步社区《UNIX编程环境》一书中的第5章,第5.3节,作者:【美】Brian W. Kernighan , Rob Pike著,更多章节内容可以访问云栖社区“异步社区”公众号查看

5.3 while和until循环:观察情况

在第3章中,for循环用于一些简单的迭代程序。一般地,for对一组文件名进行循环,如在for i in .c中;或对shell程序的所有参数进行循环,如for i in $。但实际上,shell中的for循环可以有更大的用途,如在which里的for循环。

shell有3种循环:for、while和until。其中for是最常用的一种循环,对于循环变量集中的每一个元素,它执行一次循环体内的一组命令。最常用的循环变量是文件名。while循环和until循环利用命令的退出状态来控制循环体内命令的执行。循环体一直执行,直至作为条件的命令返回状态为非0(对于while循环)或0(对于until循环)。while循环和until循环除了对命令的退出状态进行不同的解释之外,其他完全相同。下面是各种循环的基本格式:

screenshot

在第二种形式的for循环中,空的循环参数表示$*,这是常用的缩写形式。

控制while或until的条件命令可以是任何命令。例如,下面是一个观察某人(比如Mary)登录情况的循环:

screenshot

其中sleep命令用于挂起60秒,它总能正确执行(除非发生中断),因此总返回“成功”,这样,这个循环每分钟检查一次,查看Mary是否已登录。

这一版本有个缺点,如果Mary已经登录,也必须等60秒后才能知道Mary登录的信息。还有,一旦Mary已经登录到系统中,你就会每60秒接收到一个报告。可以将这个程序修改一下,使用until循环来编写,此时,如果Mary已登录到系统,你不需延迟就可以立即得到Mary的登录信息:

screenshot

这是一个更有意思的条件。如果Mary已经登录,who¦grep mary就打印出who列表中mary这一行,并返回“真”值,因为grep返回的状态表示它是否找到了匹配的内容,管道命令的退出状态是最后一个元素的退出状态。

最后,我们可以将这条命令包装起来,给它取一个名字,并安装到系统中:

screenshot

来同时观察多个人的登录情况。

作为一个更复杂的例子,我们考虑一个功能增强的who命令:它不仅能观察所有人的登录情况,并能及时报告用户登录或退出系统的情况。它的基本结构很简单:每分钟运行一次who命令,并与一分钟前的输出情况相比较,如果有不同,则报告发生的改变。who命令的输出将保存在一个文件里,我们将这个文件保存在目录/tmp中。为了区分我们的文件和其他进程的文件,可以将shell变量$$(shell命令的进程标识码)放在文件名里,这是一种常用的方法。将命令的名字编码到临时文件名中是系统管理员常用的手段之一。各种命令(包括watchwho命令)常常把文件放在/tmp目录中,最好了解是哪个命令在这么做。

screenshot

“:”是shell的内部命令,它仅仅评估它的参数,然后返回“真”。在这里,我们也可以用true命令代替它。true命令仅仅返回一个“真”的退出状态。(还有一个false命令。)但是,“:”不需要执行文件系统中的命令,所以它比true命令效率更高一些。

diff命令的输出用<和>区分来自两个文件中的不同数据;awk程序处理diff输出,并以更容易理解的格式显示出来。注意,整个while循环的结果通过管道送入awk,而不是每分钟刷新一次awk。sed不适用于这种处理情况,因为它的输出总是比输入落后一行,即总有一行的输入正在处理,没有打印,这样会导致不必要的延迟。

old生成时是一个空文件,所以watchwho第一次输出的内容是当前所有登录的用户清单。如果用命令who>$old建立old的初值,那么watchwho将只打印用户登录的变化情况,这取决于习惯的不同。

另一个循环程序可以定时地查看信箱,当信箱的内容变化时,程序打印“you have mail”。对shell的内部机制来说,使用MAIL变量是很有用的方法,我们的实现使用了shell变量替代文件,来解释这种差别。
screenshot

这里再次用到了awk程序,确保只有mailbox增长时才打印消息,而不是变化时,否则,当你删除邮件信息时也会收到消息。(shell的内部版本就受到这一缺点的限制。)

时间间隔仍然设为60秒。但在命令行提供了一个参数,如果键入下面的命令:

screenshot

就使用新的时间参数。如果提供了时间参数,shell变量t被设为对应的时间间隔,如果提供时间参数,默认的时间间隔为60秒,由下面这一行确定:
screenshot

这是shell的另一个特点。

${var}等价于$var,它可以用来避免变量名与字母或数字组成的字符串相混杂所引起的问题:

screenshot

大括号内的某些特殊字符可以指定对变量进行特殊处理。如果该变量没有定义,并且在变量名之后带有一个问号,则打印问号后面的字符串,然后退出shell(除非是交互情况)。如果没有提供问号后的信息,则打印标准的输出信息:

screenshot

注意,shell产生的信息中总是包括未定义变量的名字。

另一种形式是变量${var-thing}。当var有定义时,其值为$var;当var没有定义时,其值为thing。${var=thing}的情形与其相仿,但会把$var的值置为thing:
screenshot

变量取值规则在表5-3中列出。
screenshot

回到我们原来的例子:

screenshot

把t设为$1,如果没有提供参数,t设为60。

相关文章
|
Unix 程序员 C语言
《UNIX编程环境》——导读
本书的目的是传播UNIX程序设计的基本原则,由于这个基本原则是以程序间的关系为基础的,因此我们必须用大量的篇幅专门对单个的工具进行讨论,但同时贯穿了程序组合的主题和运用程序进行创建程序的内容。
1728 0
|
Unix Shell C语言
《UNIX编程环境》——5.10 后记
shell是一种很好的编程语言,虽然它的语法有些特殊。shell属于高级语言,它的操作对象为整个程序。由于shell是交互式语言,所以shell程序能够交互式地开发,可以逐级求精直至它能够令人满意地工作。
1737 0
|
Unix Shell Perl
《UNIX编程环境》——5.9 get和put:追踪文件变动
程序在开发过程中不断地改正错误和增加新功能。版本追踪往往是不可少的。特别是有的用户把程序移植到其他的机器上使用—他们常常跑回来问“在我们的版本之后又有哪些改动”,或者“这个那个错误是怎么改的”。
1569 0
|
Unix Shell
《UNIX编程环境》——5.8 news命令:社团服务信息
我们在第1章提到您的系统可以有一个news命令,用以报告用户社团方面的信息。大部分系统都提供新闻服务,尽管命令名和命令细节有所不同。这里给出一个news命令,不是要代替原有的本地命令,而旨在说明在shell里编写这样一个程序是多么地容易。
1266 0
|
Unix Shell C语言
《UNIX编程环境》——5.7 pick命令:空格和参数
本节书摘来自异步社区《UNIX编程环境》一书中的第5章,第5.7节,作者:【美】Brian W. Kernighan , Rob Pike著,更多章节内容可以访问云栖社区“异步社区”公众号查看
1566 0
|
Unix Shell
《UNIX编程环境》——5.6 zap:使用名字终止进程
kill命令只能通过指定进程号来终止进程。要终止某个后台进程时,一般要运行ps命令以得到进程标识号,然后再把它作为kill的参数输入。通过一个命令程序打印一个参数,再把这个参数手工输入到另一个命令中,这个方法似乎有些笨拙。
1303 0
|
Unix Shell
《UNIX编程环境》——5.4 trap:捕获中断
如果在运行watchwho时突然按下Delete键或挂断电话,在目录/tmp中,将保存一个或两个临时文件。Watchwho应该在退出之前清除这些暂存文件。我们需要一定的手段来检测各种中断事件,并进行恢复处理。
1605 0
|
Unix Shell Perl
《UNIX编程环境》——5.2 which
建立自己的命令版本,如cal命令的新版本,会带来一些其他的问题。最明显的例子是,如果Mary一起工作,并且以mary登录,则此时的cal还是标准的版本,除非Mary把新的cal命令连接到她的bin目录里。你可能会非常疑惑—原先的cal命令给出的错误信息不足以使人弄清发生错误的原因。
1890 0
|
Unix Shell
《UNIX编程环境》——第5章 shell程序设计 5.1 定制cal命令
和其他很多命令一样,shell程序的使用细节通常可以通过实践很快地掌握。shell手册常常不易于理解,而一个好的例子有时是将问题解释清楚的最好方法。鉴于这一原因,本章围绕着程序实例而不是围绕着shell的特性来组织,是shell编程指南,而不是shell所有功能的罗列。
1707 0
|
Unix 程序员 编译器
《UNIX编程环境》——1.5 UNIX系统的其余部分
UNIX系统中的内容远远多于本章中所讨论的内容,也远比本书的内容多。现在,你应可放心地使用系统,特别是要尽量使用手册。当对如何使用命令有疑问时,应查询手册。
1038 0