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

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循环除了对命令的退出状态进行不同的解释之外,其他完全相同。下面是各种循环的基本格式:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

这是shell的另一个特点。

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

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

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

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

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

回到我们原来的例子:

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

时间: 2025-01-19 11:17:13

《UNIX编程环境》——5.3 while和until循环:观察情况的相关文章

《UNIX编程环境》——5.10 后记

5.10 后记 当需要编写一个新程序时,自然立刻会想到如何用你最喜欢的语言来编写这个程序.对我们来说,最常用的语言是shell. shell是一种很好的编程语言,虽然它的语法有些特殊.shell属于高级语言,它的操作对象为整个程序.由于shell是交互式语言,所以shell程序能够交互式地开发,可以逐级求精直至它能够令人满意地工作.如果是一个面向更多的用户,可以对shell程序进一步改造,使之更精巧和更实用,以满足广泛使用的需要.不能用shell程序高效地解决问题的情况微乎其微.如果遇到这种例外

《UNIX编程环境》——导读

**前言**"UNIX安装的数量已经增加了10倍,预期还将更多." -UNIX程序员手册,1972年6月第2版 UNIX1操作系统是1969年首次在贝尔实验室的一台丢弃的DEC PDP-7计算机上启用的.当时Ken Thompson从Rudd Canaday.Doug McIlroy.Joe Ossanna和Dennis Ritchie那里获得理念和支持,编写了小型通用分时系统,其适用性能良好,足以吸引热心的用户,并最终为一台较大的计算机-PDP-11/20的购买提供了充分的可靠性.系

《UNIX编程环境》——1.4 shell

1.4 shell 当系统印出提示符$,你键入命令并得到了执行时,此时并不是内核在与读者对话,而是与一个称为命令解释器或外壳shell的在对话.shell是同date或who一样的普通程序,尽管它可以处理一些不同寻常的事.shell存在于用户和内核机制之间的事实对用户是有帮助的,有些会在这里说明.下面是三个要点. 文件名简写:可以通过指定文件名的模式来选取一套文件名作为程序的变量-shell会找出匹配该模式的文件名. 输入输出重定向:可以把任何程序的输出送到一个文件中而不是终端上,并当作来自文件

《UNIX编程环境》——第1章 初学UNIX 1.1起步

第1章 初学UNIX 第1章初学UNIX 什么是UNIX?狭义地看,它是一个分时操作系统内核,即一个控制计算机的资源并将其分配给用户的程序.它让用户运行其程序,并控制与机器连接的外围设备(硬盘.终端.打印机等),提供一个文件系统用以管理诸如程序.数据及文档等长期存储的信息. 广义地看,UNIX通常不仅包含内核,还包括一些基本程序,如编译器.编辑器.命令语言.用以复制和显示文件的程序等. 从更广的角度来看,UNIX可以包括由用户开发的.运行于用户的UNIX操作系统上的程序,如文档处理工具.统计分析

《UNIX编程环境》——5.6 zap:使用名字终止进程

5.6 zap:使用名字终止进程 kill命令只能通过指定进程号来终止进程.要终止某个后台进程时,一般要运行ps命令以得到进程标识号,然后再把它作为kill的参数输入.通过一个命令程序打印一个参数,再把这个参数手工输入到另一个命令中,这个方法似乎有些笨拙.为什么不写一个程序,如zap,自动完成这些工作呢? 原因之一是终止进程是个危险的操作,执行时必须小心谨慎.一个保险的办法是交互地运行zap,用pick命令选择要终止的进程. 先简要回顾一下pick的功能:pick顺次打印它的每个参数,并请求用户

《UNIX编程环境》——5.5 overwrite:改写文件

5.5 overwrite:改写文件 sort排序命令有一个选顶-o,表示覆盖文件: 如果filel和file2是同一个文件,重定向符号>在排序之前就把输入文件截断.然而,加上-o选项的命令将能正常工作,因为在输出文件建立前,sort先将输入排序并存放在一个临时文件中. 很多其他命令也可用-o选择.例如,sed可以编辑文件如下: 要对所有这样的命令都加上选项-o显然是不现实的.另外,这种做法也不可取:最好是将功能集中起来处理,就像shell使用运算符>那样.我们给出一个程序overwrite完

《UNIX编程环境》——1.2 文件和常用命令

1.2 文件和常用命令 在UNIX系统中信息存储在文件中,它很像日常的办公室文件.每个文件有名字.内容.存放地点以及某些管理信息,诸如所有者以及文件大小等.文件可能是一封信,或者是人名及地址清单,或者是源程序,或者是供某个程序用的数据,甚至是程序的可执行形式以及其他的非文本类型材料. UNIX文件组织结构使你可以维护自己的文件而不会影响其他人的文件,并且也防止他人干涉你的文件.UNIX系统有大量的程序可操作文件,但是现在,我们只介绍最频繁使用的那些.第2章是关于文件系统的具体讨论,其中介绍了许多

《UNIX编程环境》——5.7 pick命令:空格和参数

5.7 pick命令:空格和参数 我们已经接触了书写shell的pick命令需要的多数命令.我们只需要一种新的机制来接收用户输入.shell内部命令read提供了这一功能,即从标准输入读一行正文,并把读到的文本(不含换行)赋给命名变量: read最常用于注册时在.profile文件里设置环境,主要是建立shell环境变量,如TERM. read只能读取标准输入,而且不能被重定向.shell内部命令(与控制流原语不同,如for)都不能使用>或<重定向: 这也许可以说是shell的一个缺陷,但这就

《UNIX编程环境》——5.2 which

5.2 which 建立自己的命令版本,如cal命令的新版本,会带来一些其他的问题.最明显的例子是,如果Mary一起工作,并且以mary登录,则此时的cal还是标准的版本,除非Mary把新的cal命令连接到她的bin目录里.你可能会非常疑惑-原先的cal命令给出的错误信息不足以使人弄清发生错误的原因.但是这只是这类问题的一个例子.因为shell通过PATH指定的一组目录搜索命令,得到的可能不是所期望的版本.例如,键入一条命令:echo,而实际运行的文件全路径名可能是./echo./bin/ech

《UNIX编程环境》——5.4 trap:捕获中断

5.4 trap:捕获中断 如果在运行watchwho时突然按下Delete键或挂断电话,在目录/tmp中,将保存一个或两个临时文件.Watchwho应该在退出之前清除这些暂存文件.我们需要一定的手段来检测各种中断事件,并进行恢复处理. 按Delete键时,一个中断信号会送给终端上正在运行的所有进程:同样地,当挂断电话时,会传送一个挂断信号.其他信号发生的情形亦同.除非程序有专门处理中断信号措施,否则,中断信号将一律终止程序的运行.如果是中断信号,后台运行的进程(使用&运行)能得到保护,但如果是