通用线程:Awk 实例( 五 )


address.awk
BEGIN { FS="n" RS=""}{ print $1 ", " $2 ", " $3}
如果这个脚本保存为 address.awk,地址数据存储在文件 address.txt 中,可以通过输入 "awk -f address.awk address.txt" 来执行这个脚本 。此代码将产生以下输出:
Jimmy the Weasel, 100 Pleasant Drive, San Francisco, CA 12345Big Tony, 200 Incognito Ave., Suburbia, WA 67890
OFS 和 ORS
在 address.awk 的 print 语句中,可以看到 awk 会连接(合并)一行中彼此相邻的字符串 。我们使用此功能在同一行上的三个字段之间插入一个逗号和空格 (", ") 。这个方法虽然有用,但比较难看 。与其在字段间插入 ", " 字符串,倒不如让通过设置一个特殊 awk 变量 OFS,让 awk 完成这件事 。请参考下面这个代码片断 。
print "Hello", "there", "Jim!"
这行代码中的逗号并不是实际文字字符串的一部分 。事实上,它们告诉 awk "Hello"、"there" 和 "Jim!" 是单独的字段,并且应该在每个字符串之间打印 OFS 变量 。缺省情况下,awk 产生以下输出:
Hello there Jim!
这是缺省情况下的输出结果,OFS 被设置成 " ",单个空格 。不过,我们可以方便地重新定义 OFS,这样 awk 将插入我们中意的字段分隔符 。以下是原始 address.awk 程序的修订版,它使用 OFS 来输出那些中间的 ", " 字符串:
address.awk 的修订版
BEGIN { FS="n" RS="" OFS=", "}{ print $1, $2, $3}
awk 还有一个特殊变量 ORS,全称是“输出记录分隔符” 。通过设置缺省为换行 ("n") 的 OFS,我们可以控制在 print 语句结尾自动打印的字符 。缺省 ORS 值会使 awk 在新行中输出每个新的 print 语句 。如果想使输出的间隔翻倍,可以将 ORS 设置成 "nn" 。或者,如果想要用单个空格分隔记录(而不换行),将 ORS 设置成 "" 。
将多行转换成用 tab 分隔的格式
假设我们编写了一个脚本,它将地址列表转换成每个记录一行,且用 tab 定界的格式,以便导入电子表格 。使用稍加修改的 address.awk 之后,就可以清楚地看到这个程序只适合于三行的地址 。如果 awk 遇到以下地址,将丢掉第四行,并且不打印该行:
Cousin VinnieVinnie"s Auto Shop300 City AlleySosueme, OR 76543
要处理这种情况,代码最好考虑每个字段的记录数量,并依次打印每个记录 。现在,代码只打印地址的前三个字段 。以下就是我们想要的一些代码:
适合具有任意多字段的地址的 address.awk 版本
BEGIN { FS="n" RS="" ORS="" } { x=1 while ( x首先,将字段分隔符 FS 设置成 "n",将记录分隔符 RS 设置成 "",这样 awk 可以象以前一样正确分析多行地址 。然后,将输出记录分隔符 ORS 设置成 "",它将使 print 语句在每个调用结尾不输出新行 。这意味着如果希望任何文本从新的一行开始,那么需要明确写入 print "n" 。
在主代码块中,创建了一个变量 x 来存储正在处理的当前字段的编号 。起初,它被设置成 1 。然后,我们使用 while 循环(一种 awk 循环结构,等同于 C 语言中的 while 循环),对于所有记录(最后一个记录除外)重复打印记录和 tab 字符 。最后,打印最后一个记录和换行;此外,由于将 ORS 设置成 "",print 将不输出换行 。程序输出如下,这正是我们所期望的:
我们想要的输出 。不算漂亮,但用 tab 定界,以便于导入电子表格
Jimmy the Weasel 100 Pleasant Drive San Francisco, CA 12345 Big Tony 200 Incognito Ave. Suburbia, WA 67890Cousin Vinnie Vinnie"s Auto Shop 300 City Alley Sosueme, OR 76543
循环结构
我们已经看到了 awk 的 while 循环结构,它等同于相应的 C 语言 while 循环 。awk 还有 "do...while" 循环,它在代码块结尾处对条件求值,而不象标准 while 循环那样在开始处求值 。它类似于其它语言中的 "repeat...until" 循环 。以下是一个示例:

推荐阅读