通用线程 -- sed 实例 3
2004-11-15 20:14
316 查看
在这篇 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 系统,该脚本将为您执行必需的格式转换。
我已记不清有多少次在下载一些示例脚本或 C 代码之后,却发现它是 DOS/Windows 格式。虽然很多程序不在乎 DOS/Windows 格式的 CR/LF 文本文件,但是有几个程序却在乎 -- 最著名的是 bash,只要一遇到回车,它就会出问题。以下 sed 调用将把 DOS/Windows 格式的文本转换成可信赖的 UNIX 格式:
反转行 下面是另一个方便的小脚本。与大多数 Linux 发行版中包括的 "tac" 命令一样,该脚本将反转文件中行的次序。"tac" 这个名称可能会给人以误导,因为 "tac" 不反转行中字符的位置(左和右),而是反转文件中行的位置(上和下)。用 "tac" 处理以下文件:
反转解释 首先,该脚本包含三个由分号隔开的单独 sed 命令:'1!G'、'h' 和 '$!d'。现在,需要好好理解用于第一个和第三个命令的地址。如果第一个命令是 '1G',则 'G' 命令将只应用第一行。然而,还有一个 '!' 字符 -- 该 '!' 字符忽略该地址,即,'G' 命令将应用到除第一行之外的所有行。'$!d' 命令与之类似。如果命令是 '$d',则将只把 'd' 命令应用到文件中的最后一行('$' 地址是指定最后一行的简单方式)。然而,有了 '!' 之后,'$!d' 将把 'd' 命令应用到除最后一行之外的所有行。现在,我们所要理解的是这些命令本身做什么。 当对上面的文本文件执行反转脚本时,首先执行的命令是 'h'。该命令告诉 sed 将模式空间(保存正在处理的当前行的缓冲区)的内容复制到保留空间(临时缓冲区)。然后,执行 'd' 命令,该命令从模式空间中删除 "foo",以便在对这一行执行完所有命令之后不打印它。 现在,第二行。在将 "bar" 读入模式空间之后,执行 'G' 命令,该命令将保留空间的内容 ("foo/n") 附加到模式空间 ("bar/n"),使模式空间的内容为 "bar/n/foo/n"。'h' 命令将该内容放回保留空间保护起来,然后,'d' 从模式空间删除该行,以便不打印它。 对于最后的 "oni" 行,除了不删除模式空间的内容(由于 'd' 之前的 '$!')以及将模式空间的内容(三行)打印到标准输出之外,重复同样的步骤。 现在,要用 sed 执行一些强大的数据转换。 sed QIF 魔法 过去几个星期,我一直想买一份 Quicken 来结算我的银行帐户。Quicken 是一个非常好的金融程序,当然会成功地完成这项工作。但是,经过考虑之后,我觉得自己可以轻易编写某个软件来结算我的支票簿。我想,毕竟,我是个软件开发人员! 我开发了一个很好的小型支票簿结算程序(使用 awk),它通过分析包含我的所有交易的文本文件的语法来计算余额。略微调整之后,我将其改进,以便可以象 Quicken 那样跟踪不同的贷款和借款类别。但是,我还要添加一个特性。最近,我将帐户转移到一家有联机 Web 帐户界面的银行。有一天,我注意到,这家银行的 Web 站点允许以 Quicken 的 .QIF 格式下载我的帐户信息。我马上觉得,如果可以将该信息转换成文本格式,那就太棒了。 两种格式的故事 在查看 QIF 格式之前,先看一下我的 checkbook.txt 格式:
在处理象这样重要的 sed 项目时,不要气馁 -- sed 允许您将数据逐渐修改成最终形式。在进行当中,可以继续细化 sed 脚本,直到输出与预期的完全一样为止。无需在试第一次时就保证其完全正确。 要开始,首先创建一个名为 "qiftrans.sed" 的文件,然后开始修改数据:
花括号中的第一个命令将把如下行:
细化 现在进一步细化:
结束尝试 最后一行除去数字后的逗号。它把如 "3,231.00" 这样的美元金额转换成我使用的格式 "3231.00"。现在,让我们看一下最终脚本: 最终的“QIF 到文本”脚本
既然您理解该命令本身的工作原理,让我们看一下分支。如果看一下分支规则表达式,将看到它与后面依次跟有 '-'、任意数量的数字、一个 '.'、任意数量的数字和 'AMT' 的字符串 'AMT' 匹配。就象我确信您已猜到一样,该规则表达式专门处理负的美元金额。在这之前,用 'ATM' 括起美元金额,以便以后可以轻易找到它。因为规则表达式只与以 '-' 开始的美元金额匹配,所以,该分支只在恰巧处理借款时才发生。如果正处理贷款,应该将 OUTY 设置成 'misc',将 INNY 设置成 '-',并且应该除去贷款数量前面的负号。如果跟踪代码的流程,将看到实际情况正是这样。如果不执行分支,则用 '-' 替换 OUTY,用 'inco' 替换 INNY。完成了!现在输出行是完美的:
如您所见,只要循序渐进地解决问题,使用 sed 转换数据就没有那么难。不要试图使用一个 sed 命令或一下子解决所有问题。相反,要朝着目标逐步进行,并不断改进 sed 脚本,直到其输出正如您希望那样为止。sed 有许多功能,希望您已非常熟悉其内部工作原理并继续努力以进一步掌握它! 参考资料 阅读 developerWorks 上 Daniel 的前两篇 sed 文章:通用线程:sed 实例,第 1 部分和第 2 部分。 查看 Eric Pement 极佳的 sed faq。 可以在 ftp.gnu.org 找到 sed 3.02 资源。 将在 alpha.gnu.org 找到很好的新的 sed 3.02.80。 另外,Eric Pement 还有一些方便的 sed 单行程序,任何有抱负的 sed 高手都应该看一下。 如果想看好的老式书籍,O'Reilly 的 sed & awk, 2nd Edition 将是极佳选择。 可能想阅读 7th edition UNIX's sed man page(大概 1978!)。 阅读 Felix von Leitner 短小的 sed tutorial。 在 using regular expressions 中复习,发现和修改这个免费 dW 独家教程文本中的模式。 关于作者 Daniel Robbins 居住在新墨西哥州的 Albuquerque。他是 Gentoo Technologies, Inc. 的总裁兼 CEO,Gentoo Linux(用于 PC 的高级 Linux)和 Portage 系统(Linux 的下一代端口系统)的创始人。他还是 Macmillan 书籍 Caldera OpenLinux Unleashed、SuSE Linux Unleashed 和 Samba Unleashed 的作者。Daniel 自小学二年级起就与计算机结下不解之缘,那时他首先接触的是 Logo 程序语言,并沉溺于 Pac-Man 游戏中。这也许就是他至今仍担任 SONY Electronic Publishing/Psygnosis 的首席图形设计师的原因所在。Daniel 喜欢与妻子 Mary 和新出生的女儿 Hadassah 一起共度时光。可通过 drobbins@gentoo.org 与 Daniel 联系。 |
相关文章推荐
- 雷达遥感
- 通用线程 -- sed 实例 2
- 一个令人迷惑不解的圆周计算程序
- 侯捷观点--Java反射机制
- 天天学英语之1115
- 图像透明度算法
- 在Solaris下配置Java/jsp图形平台
- 目的
- 通用线程 -- sed 实例 1
- IT行业从业人,如何在你的公司站稳脚跟,良好发展
- Visual Studio 2005 Express Beta Products 下载链接
- 如何利用Win2000 Server配置路由(图)
- JS错误代码解释大全
- 处理人际关系的技巧。
- Maven 专题之一
- Tapestry入门
- 职场暗访:女大学生应聘遭遇性测试
- 取一个透明颜色
- 我的鸡下蛋了!!!
- 保安听了老板的一次闲聊而成为老板