超越单行的 awk 脚本,学习如何做邮件合并和字数统计。
awk
是 Unix 和 Linux 用户工具箱中最古老的工具之一。awk
由 Alfred Aho、Peter Weinberger 和 Brian Kernighan(即工具名称中的 A、W 和 K)在 20 世纪 70 年代创建,用于复杂的文本流处理。它是流编辑器 sed
的配套工具,后者是为逐行处理文本文件而设计的。awk
支持更复杂的结构化程序,是一门完整的编程语言。
本文将介绍如何使用 awk
完成更多结构化的复杂任务,包括一个简单的邮件合并程序。
awk 的程序结构
awk
脚本是由 {}
(大括号)包围的功能块组成,其中有两个特殊的功能块,BEGIN
和 END
,它们在处理第一行输入流之前和最后一行处理之后执行。在这两者之间,块的格式为:
-
模式 { 动作语句 }
当输入缓冲区中的行与模式匹配时,每个块都会执行。如果没有包含模式,则函数块在输入流的每一行都会执行。
另外,以下语法可以用于在 awk
中定义可以从任何块中调用的函数。
-
function 函数名(参数列表) { 语句 }
这种模式匹配块和函数的组合允许开发者结构化的 awk
程序,以便重用和提高可读性。
awk 如何处理文本流
awk
每次从输入文件或流中一行一行地读取文本,并使用字段分隔符将其解析成若干字段。在 awk
的术语中,当前的缓冲区是一个记录。有一些特殊的变量会影响 awk
读取和处理文件的方式:
-
FS
(字段分隔符)。默认情况下,这是任何空格字符(空格或制表符)。 -
RS
(记录分隔符)。默认情况下是一个新行(n
)。 -
NF
(字段数)。当awk
解析一行时,这个变量被设置为被解析出字段数。 -
$0:
当前记录。 -
$1
、$2
、$3
等:当前记录的第一、第二、第三等字段。 -
NR
(记录数)。迄今已被awk
脚本解析的记录数。
影响 awk
行为的变量还有很多,但知道这些已经足够开始了。
单行 awk 脚本
对于一个如此强大的工具来说,有趣的是,awk
的大部分用法都是基本的单行脚本。也许最常见的 awk
程序是打印 CSV 文件、日志文件等输入行中的选定字段。例如,下面的单行脚本从 /etc/passwd
中打印出一个用户名列表:
-
awk -F":" '{print $1 }' /etc/passwd
如上所述,$1
是当前记录中的第一个字段。-F
选项将 FS
变量设置为字符 :
。