使用 AWK 进行快速而粗略的数据提取
许多年前,大概有 20 年了,在 comp Usenet 新闻组上经常有人提到使用最小的工具来完成工作。也就是说,有人会问一个快速而粗略的方法来做某事。接下来的回复通常包括一个 C 解决方案,然后是一个 AWK 解决方案,然后是一个 sed 解决方案等等。
今天,我在解决问题时仍然尝试使用这种理念。在这个特定的例子中,如下所述,我选择了 AWK。如果你们这些老前辈正在阅读这篇文章,我希望你们会提出一个基于 sed 的解决方案。
我订阅了每日货币汇率摘要。这是一项免费服务,您也可以订阅 - 只需访问这里。 大部分时间,我会快速浏览一下美元兑欧元的汇率,然后保存电子邮件。 有时候我只是简单地保存消息。我保存它们是因为我一直认为,总有一天我会编写一个程序来显示汇率趋势。但这样做一直是一个低优先级。
前段时间,当我在看一些保存的电子邮件消息时,我意识到,虽然编写一个花哨的图形程序来显示趋势是一项低优先级任务,但编写一个快速而粗略的黑客程序则不然。编写这种黑客程序所需的时间比我花在随机抽样上的时间要少。
我想做的是跟踪日期和数字,然后生成趋势的极简图形显示。 第一步是查看数据。 这是消息的一部分的摘录
>From list@en.ucc.xe.net Wed Sep 10 12:22:53 2003 ... XE.com's Currency Update Service writes: Here is today's Currency Update, a service of XE.com. Please read the copyright, terms of use agreement, and information sections at the end of this message. CUS5D0B3D5C16D9 ____________________________________________________________________________ If you find our free currency e-mail updates useful, please forward this message to a friend! Subscribe for free at: http://www.xe.com/cus/ ____________________________________________________________________________ <PRE> Rates as of 2003.09.09 20:46:35 UTC (GMT). Base currency is EUR. Currency Unit EUR per Unit Units per EUR ================================ =================== =================== USD United States Dollars 0.890585 1.12286 EUR Euro 1.00000 1.00000 GBP United Kingdom Pounds 1.41659 0.705920 CAD Canada Dollars 0.651411 1.53513 ... </PRE> For help reading this mailout, refer to: http://www.xe.com/cus/sample.htm ...
... 行表示我丢弃了很多不感兴趣的行。
我需要从这些电子邮件消息中获取三件事才能生成我的报告
“Rates as of”行,以获取日期
“USD”行,以获取实际转换率
</PRE> 行,告诉我打印信息并清除我的变量。 如果数据良好,我实际上不必清除它们,但这似乎是检测错误数据的好方法。 这是一个快速的 hack,是的,但不是一个令人厌恶的快速 hack。
解决方案的数字部分非常简单。 只需获取日期信息和汇率信息。 当我到达 </PRE> 行时,将其打印出来。
图形部分通过打印与汇率相对应的多个加号来实现。 为了获得体面的分辨率,我需要宽幅打印或某种偏移。 我选择了偏移,假设欧元不会跌破 0.90 美元,考虑到它一直走的方向,这非常安全。
最后,我想要一个标题。 使用 AWK 的 BEGIN 块,我放入了几个打印语句。 我不喜欢计算字符,所以我定义了变量over是为了放置在标题信息之前以对齐所有内容的空格数。 这样做仅仅意味着我必须运行程序,看看我离得有多远并调整变量。 这是代码
BEGIN { over = " " print over, " Cost of Euros in $ by date" print over, ".9 1.0 1.1 1.2 1.3" print over, "| | | | |" } /Rates as of/ { date = $4 } /^USD/ { rate = $6 } /^<\/PRE>/ { printf "%s %6.3f ", date, rate rc = (rate - .895) * 100 for (i=0; i < rc; i++) printf "+" printf "\n" date = "xxx" rate = 0 }
使用邮件文件作为输入运行程序会打印所有结果行,但顺序与邮件文件中的数据顺序相同。 所以是 sort 程序来拯救。 输出中的第一个字段是日期,并且仔细选择标题行的第一个字符意味着一切都正确排序,没有任何选项。 因此,要运行 AWK 程序,请使用
awk -f cc.as messages | sort
你就能得到你漂亮的报告。 通过管道将结果传递给more如果您有很多行要查看。
这是来自 AWK 脚本的输出示例
Cost of Euros in $ by date .9 1.0 1.1 1.2 1.3 | | | | | 2003.01.02 1.036 +++++++++++++++ ... 2003.08.28 1.087 ++++++++++++++++++++ 2003.08.29 1.098 +++++++++++++++++++++ 2003.08.31 1.099 +++++++++++++++++++++ 2003.09.01 1.097 +++++++++++++++++++++ 2003.09.02 1.081 +++++++++++++++++++ 2003.09.04 1.094 ++++++++++++++++++++ 2003.09.05 1.110 ++++++++++++++++++++++ 2003.09.07 1.110 ++++++++++++++++++++++ 2003.09.08 1.107 ++++++++++++++++++++++ 2003.09.09 1.123 +++++++++++++++++++++++ 2003.09.10 1.121 +++++++++++++++++++++++ 2003.09.11 1.120 +++++++++++++++++++++++ 2003.09.12 1.129 ++++++++++++++++++++++++ 2003.09.14 1.127 ++++++++++++++++++++++++ 2003.09.15 1.128 ++++++++++++++++++++++++ 2003.09.16 1.117 +++++++++++++++++++++++ 2003.09.17 1.129 ++++++++++++++++++++++++ 2003.09.18 1.124 +++++++++++++++++++++++ 2003.09.19 1.138 +++++++++++++++++++++++++
好的,sed 专家们,开始吧。
版权所有 (c) 2003, Phil Hughes。 最初发表在 Linux Gazette 第 95 期中。 版权所有 (c) 2003, Specialized Systems Consultants, Inc.
Phil Hughes 是 SSC Publishing, Ltd. 的集团出版人。