通用线程:Awk 实例


DanIEl Robbins (drobbins@gentoo.org)
第一部分
Awk 是一种非常好的语言,同时有一个非常奇怪的名称 。在本系列(共三篇文章)的第一篇文章中,Daniel Robbins 将使您迅速掌握 awk 编程技巧 。随着本系列的进展,将讨论更高级的主题,最后将演示一个真正的高级 awk 演示程序 。
捍卫 awk
在本系列文章中,我将使您成为精通 awk 的编码人员 。我承认,awk 并没有一个非常好听且又非常“时髦”的名字 。awk 的 GNU 版本(叫作 gawk)听起来非常怪异 。那些不熟悉这种语言的人可能听说过 "awk",并可能认为它是一组落伍且过时的混乱代码 。它甚至会使最博学的 Unix 权威陷于错乱的边缘(使他不断地发出 "kill -9!" 命令,就象使用咖啡机一样) 。
的确,awk 没有一个动听的名字 。但它是一种很棒的语言 。awk 适合于文本处理和报表生成,它还有许多精心设计的特性,允许进行需要特殊技巧程序设计 。与某些语言不同,awk 的语法较为常见 。它借鉴了某些语言的一些精华部分,如 C 语言、python 和 bash(虽然在技术上,awk 比 python 和 bash 早创建) 。awk 是那种一旦学会了就会成为您战略编码库的主要部分的语言 。
第一个 awk
让我们继续,开始使用 awk,以了解其工作原理 。在命令行中输入以下命令:
$ awk "{ print }" /etc/passwd
您将会见到 /etc/passwd 文件的内容出现在眼前 。现在,解释 awk 做了些什么 。调用 awk 时,我们指定 /etc/passwd 作为输入文件 。执行 awk 时,它依次对 /etc/passwd 中的每一行执行 print 命令 。所有输出都发送到 stdout,所得到的结果与与执行catting /etc/passwd完全相同 。
现在,解释 { print } 代码块 。在 awk 中,花括号用于将几块代码组合到一起,这一点类似于 C 语言 。在代码块中只有一条 print 命令 。在 awk 中,如果只出现 print 命令,那么将打印当前行的全部内容 。
这里是另一个 awk 示例,它的作用与上例完全相同:
$ awk "{ print $0 }" /etc/passwd
在 awk 中,$0 变量表示整个当前行,所以 print 和 print $0 的作用完全一样 。
如果您愿意,可以创建一个 awk 程序,让它输出与输入数据完全无关的数据 。以下是一个示例:
$ awk "{ print "" }" /etc/passwd
只要将 "" 字符串传递给 print 命令,它就会打印空白行 。如果测试该脚本,将会发现对于 /etc/passwd 文件中的每一行,awk 都输出一个空白行 。再次说明, awk 对输入文件中的每一行都执行这个脚本 。以下是另一个示例:
$ awk "{ print "hiya" }" /etc/passwd
运行这个脚本将在您的屏幕上写满 hiya 。:)
多个字段
awk 非常善于处理分成多个逻辑字段的文本,而且让您可以毫不费力地引用 awk 脚本中每个独立的字段 。以下脚本将打印出您的系统上所有用户帐户的列表:【通用线程:Awk 实例】$ awk -F":" "{ print $1 }" /etc/passwd
上例中,在调用 awk 时,使用 -F 选项来指定 ":" 作为字段分隔符 。awk 处理 print $1 命令时,它会打印出在输入文件中每一行中出现的第一个字段 。以下是另一个示例
$ awk -F":" "{ print $1 $3 }" /etc/passwd
以下是该脚本输出的摘录
halt7operator11root0shutdown6sync5bin1....etc.
如您所见,awk 打印出 /etc/passwd 文件的第一和第三个字段,它们正好分别是用户名和用户标识字段 。现在,当脚本运行时,它并不理想 -- 在两个输出字段之间没有空格!如果习惯于使用 bash 或 python 进行编程,那么您会指望 print $1 $3 命令在两个字段之间插入空格 。然而,当两个字符串在 awk 程序中彼此相邻时,awk 会连接它们但不在它们之间添加空格 。以下命令会在这两个字段中插入空格:
$ awk -F":" "{ print $1 " " $3 }" /etc/passwd

推荐阅读