通用线程--sed 实例,第3部分


通用线程 -- sed 实例,第 3 部分
在这篇 sed 系列的总结性文章中,DanIEl Robbins 带您体验 sed 的真正力量 。在介绍完几个重要的 sed 脚本之后,他将通过将一个 Quicken .QIF 文件转换成可读文本格式来演示一些基本 sed 脚本的编写 。该转换脚本不仅实用,而且还是展现 sed 脚本编写能力的极佳示例 。强健的 sed
在第二篇 sed 文章中,我提供了一些示例来演示 sed 的工作原理,但是它们当中很少有示例能实际做特别有用的事 。在这篇 sed 系列的最后文章中,我要改变那种方式,并使用 sed 来做实际的事 。我将为您显示几个示例,它们不仅演示 sed 的能力,而且还做一些真正巧妙(和方便)的事 。例如,在本文的后半部,将为您演示如何设计一个 sed 脚本来将 .QIF 文件从 Intuit 的 Quicken 金融程序转换成具有良好格式的文本文件 。在那样做之前,我们将看一下不怎么复杂但却很有用的 sed 脚本 。文本转换
第一个实际脚本将 Unix 风格的文本转换成 Dos/Windows 格式 。您可能知道,基于 DOS/Windows 的文本文件在每一行末尾有一个 CR(回车)和 LF(换行),而 UNIX 文本只有一个换行 。有时可能需要将某些 UNIX 文本移至 Windows 系统,该脚本将为您执行必需的格式转换 。$ sed -e "s/$/r/" myunix.txt > mydos.txt

在该脚本中,"$" 规则表达式将与行的末尾匹配,而 "r" 告诉 sed 在其之前插入一个回车 。在换行之前插入回车,立即,每一行就以 CR/LF 结束 。请注意,仅当使用 GNU sed 3.02.80 或以后的版本时,才会用 CR 替换 "r" 。如果还没有安装 GNU sed 3.02.80,请在我的第一篇 sed 文章中查看如何这样做的说明 。我已记不清有多少次在下载一些示例脚本或 C 代码之后,却发现它是 DOS/Windows 格式 。虽然很多程序不在乎 DOS/Windows 格式的 CR/LF 文本文件,但是有几个程序却在乎 -- 最著名的是 bash,只要一遇到回车,它就会出问题 。以下 sed 调用将把 DOS/Windows 格式的文本转换成可信赖的 UNIX 格式:$ sed -e "s/.$//" mydos.txt > myunix.txt

该脚本的工作原理很简单:替代规则表达式与一行的最末字符匹配,而该字符恰好就是回车 。我们用空字符替换它,从而将其从输出中彻底删除 。如果使用该脚本并注意到已经删除了输出中每行的最末字符,那么,您就指定了已经是 UNIX 格式的文本文件 。也就没必要那样做了!反转行
下面是另一个方便的小脚本 。与大多数 Linux 发行版中包括的 "tac" 命令一样,该脚本将反转文件中行的次序 。"tac" 这个名称可能会给人以误导,因为 "tac" 不反转行中字符的位置(左和右),而是反转文件中行的位置(上和下) 。用 "tac" 处理以下文件:foo bar oni

....将产生以下输出:oni bar foo
【通用线程--sed 实例,第3部分】
可以用以下 sed 脚本达到相同目的:$ sed -e "1!G;h;$!d" forward.txt > backward.txt

如果登录到恰巧没有 "tac" 命令的 FreeBSD 系统,将发现该 sed 脚本很有用 。虽然方便,但最好还是知道该脚本为什么那样做 。让我们对它进行讨论 。反转解释
首先,该脚本包含三个由分号隔开的单独 sed 命令:"1!G"、"h" 和 "$!d" 。现在,需要好好理解用于第一个和第三个命令的地址 。如果第一个命令是 "1G",则 "G" 命令将只应用第一行 。然而,还有一个 "!" 字符 -- 该 "!" 字符忽略该地址,即,"G" 命令将应用到除第一行之外的所有行 。"$!d" 命令与之类似 。如果命令是 "$d",则将只把 "d" 命令应用到文件中的最后一行("$" 地址是指定最后一行的简单方式) 。然而,有了 "!" 之后,"$!d" 将把 "d" 命令应用到除最后一行之外的所有行 。现在,我们所要理解的是这些命令本身做什么 。当对上面的文本文件执行反转脚本时,首先执行的命令是 "h" 。该命令告诉 sed 将模式空间(保存正在处理的当前行的缓冲区)的内容复制到保留空间(临时缓冲区) 。然后,执行 "d" 命令,该命令从模式空间中删除 "foo",以便在对这一行执行完所有命令之后不打印它 。现在,第二行 。在将 "bar" 读入模式空间之后,执行 "G" 命令,该命令将保留空间的内容 ("foon") 附加到模式空间 ("barn"),使模式空间的内容为 "barnfoon" 。"h" 命令将该内容放回保留空间保护起来,然后,"d" 从模式空间删除该行,以便不打印它 。对于最后的 "oni" 行,除了不删除模式空间的内容(由于 "d" 之前的 "$!")以及将模式空间的内容(三行)打印到标准输出之外,重复同样的步骤 。现在,要用 sed 执行一些强大的数据转换 。sed QIF 魔法

推荐阅读