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

5.5 overwrite:改写文件

sort排序命令有一个选顶-o,表示覆盖文件:

如果filel和file2是同一个文件,重定向符号>在排序之前就把输入文件截断。然而,加上-o选项的命令将能正常工作,因为在输出文件建立前,sort先将输入排序并存放在一个临时文件中。

很多其他命令也可用-o选择。例如,sed可以编辑文件如下:

要对所有这样的命令都加上选项-o显然是不现实的。另外,这种做法也不可取:最好是将功能集中起来处理,就像shell使用运算符>那样。我们给出一个程序overwrite完成这项工作。第一种设计如下:

基本的实现思路直截了当—保存全部输入直到文件尾,然后把数据复制到参数文件:

这里使用cp命令,而不使用mv命令,从而当输出文件已存在时,访问权限和所属关系保持不变。

尽管这个版本有个诱人的优点:简单,但是它有一个致命的缺点:如果用户在cp过程中按下Delete键,原来的输入文件将被破坏。必须防止对输入文件的覆盖被任何中断终止:

如果到达原文件尾前发生了一个Delete中断,临时文件将被删除而原文件保留。备份完成后信号将被忽略,因此前一个cp不会被中断—一旦cp开始,overwrite将全力进行原文件的修改工作。

还有一个小问题。考虑下面的程序:

如果为overwrite提供输入的程序出错,它的输出将会被清零,overwrite也会尽职尽责地破坏参数文件。

这一问题有几种解决办法。overwrite可以在重写文件前请求确认,但是增加交互功能会大大削弱overwrite的优越性。overwrite可以检查其输入是否为空(利用test -z),但这种编程风格很糟糕,而且也不正确:一些输出数据会在探测到错误之前生成。

最好的解决方案是由overwrite运行并控制数据生成程序,以便检查它的退出状态。尽管这与传统和直觉相左—在一条管道中,overwrite通常放在最后,但是为了正确工作,这里它必须最先运行。所幸的是,overwrite不产生标准输出,所以这种处理没有丧失一般性。它的语法也并不陌生:time,nice和nohup都是以其他命令作为参数的命令。

下面是一个安全的版本:

shell的内部命令shift将整个参数表向左移动一个位置:$2成为$1,$3成为$2,依次类推。“$@”提供所有参数(移动后的),与$*类似,但不对参数作解释。在5.7节还要讨论这一问题。

注意,为运行用户命令而对PATH进行了重置;否则,overwrite将不能访问那些不在/bin和/usr/bin目录下的命令。

现在overwrite可以工作了(尽管有些笨拙):

(回忆一下,当for语句循环表为空时,默认等于$*。)使用@代替/表示定界符,因为@与输入字符串冲突的可能性更小。

replace把PATH设为/bin:/usr/bin,而不包括$HOME/bin。这表明overwrite必须在/usr/bin目录运行下才能使replace工作。做这一假定是为了处理简化;如果不能在/usr/bin里安装overwrite,就必须在replace里将$HOME/bin放入PATH,或者明确地写出overwrite的路径名。以后,我们假定所有命令都被有意地放在/usr/bin目录下。

练习5-17 为什么overwrite在trap中不用信号码0,从而在退出时删除文件?提示:试着在运行下列程序时按Delete键:

练习5-18 为replace命令加上选择项-v,用于在/dev/tty上打印所有变动的行。提示:s/$left/$right/g$vflag。

练习5-19 修改replace,使它可以工作于拥有任意字符的替换串。

练习5-20replace能否把程序中出现的所有变量i改为index?应该怎样修改?

练习5-21 把replace程序放在/us/bin目录是否方便和完全满足使用需要?需要时简单地键入正确的sed命令是否更加可取?为什么?

练习5-22(难)下一命令不能正常工作。解释原因并修改。

提示:参阅sh(1)中的eval。修改后程序对命令中元字符的解释产生了什么影响?

时间: 2024-11-05 16:29:23

《UNIX编程环境》——5.5 overwrite:改写文件的相关文章

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

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

《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编程环境》——5.10 后记

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

《UNIX编程环境》——1.3 目录

1.3 目录 系统可以把你的文件(如名为junk的文件)同任何其他人的相同名称的文件区分开.这个区分是依靠把文件分组成目录(文件夹),而不是像图书馆中那样把书放在架上,所以在不同目录中的文件可有相同的名称而不至于出现矛盾. 通常,每个用户都有其个人目录或主目录,也有时称为登录目录,其中只包含了属于用户他或她的文件.当登录时,用户在自己的目录中.用户可以改变工作用的目录-通常称为用户的工作目录或当前目录-但用户的主目录始终不会变化.除非用户采取特别的行动,当建立一个新文件时,它会建在当前目录中.由

《UNIX编程环境》——1.4 shell

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

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

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

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

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

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

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

《UNIX编程环境》——5.2 which

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