52. awk 程序结构
Block
典型的 awk 程序具有以下三个块。
1. BEGIN
BEGIN
块语法
BEGIN { awk-commands }
BEGIN
块在 awk 开始执行输入文件中所有行的 body
块之前仅在开始时执行一次。
BEGIN
块是打印报表标题和初始化变量的好地方。BEGIN
块中可以有一个或多个 awk 命令。- 关键字
BEGIN
应以大写形式指定。 BEGIN
块是可选的。
2. Body
body
块语法
/pattern/ {action}
输入文件中的每一行都会执行一次 body
块。
- 如果输入文件有 10 条记录,则
body
块中的命令将执行 10 次(输入文件中的每条记录执行一次)。 body
块没有关键字。 我们之前讨论过模式和动作
3. END
END
块语法
END { awk-commands }
在 awk 完成执行输入文件中所有行的 body
块之后,END
块仅在最后执行一次。
END
块是打印报表页脚和进行任何清理活动的好地方。END
块中可以有一个或多个 awk 命令。- 关键字
END
应以大写形式指定。 END
块是可选的。
工作流
awk 程序的工作流如下:
以下简单示例显示了三个 awk 块的运行情况。
$ awk 'BEGIN { FS=":";print "---header---" } \ /mail/ {print $1} \ END { print "---footer---"}' /etc/passwd ---header--- mail mailnull ---footer---
\
将其拆分为多行。
上面的示例分 3 行输入,第 1 行和第 2 行末尾有一个\
。
在上面的例子中:
'BEGIN { FS=":";print "---header---" }
是开始块,它设置字段分隔符变量FS
(稍后详细介绍),并打印标题。 这仅在主体循环之前执行一次。/mail/ {print $1}
是主体循环,包含模式和操作。即,这将在输入文件中搜索关键字"mail"
并打印第一个字段。END { print "---footer---"}'
是结束块,用于打印页脚。/etc/passwd
是输入文件。 对该文件中的每条记录执行主体循环。
除了从命令行执行上面的简单示例之外,您还可以从文件中执行它。
首先,创建以下包含 BEGIN、body 和 END 循环的myscript.awk
文件:
$ vi myscript.awk
BEGIN {
FS=":"
print "---header---"
}
/mail/ {
print $1
}
END {
print "---footer---"
}
接下来,对输入文件/etc/passwd
执行myscript.awk
,如下所示:
$ awk -f myscript.awk /etc/passwd
---header---
mail
mailnull
---footer---
请注意 awk 脚本内的注释以#
开头。 如果您正在编写复杂的 awk 脚本,请遵循最佳实践:在*.awk
文件中写入足够的注释,以便您稍后查看该文件时更容易理解。
组合示例
以下是一些随机的简单示例,向您展示 awk 块的各种组合。
Example1:仅有 body
块
awk -F: '{ print $1 }' /etc/passwd
Example2:begin
, body
, 和 end
块
awk -F: 'BEGIN { printf "username\n------\n"} \ { print $1 } \ END { print "------" }' /etc/passwd
Example3:begin
和 body
块
awk -F: 'BEGIN { print "UID"} { print $3 }' /etc/passwd
仅使用 BEGIN
块的注意事项
仅指定 BEGIN
块是有效的 awk 语法。 当您不指定主体循环时,指定输入文件是没有意义的,因为只对输入文件中的行执行主体循环。 因此,当您想使用 awk 程序执行与文件处理无关的操作时,仅使用 BEGIN
块。
在下面的示例中,我们仅使用 BEGIN
块来解释一些 awk 编程组件的工作原理。 您可以将这个想法用于您认为合适的任何事情。
只有简单的 BEGIN
块
$ awk 'BEGIN { print "Hello World!" }'
Hello World!
多个输入文件
请注意,您可以指定多个输入文件。 如果指定两个输入文件,首先将对输入文件 1 中的所有行执行主体块,接下来将对输入文件 2 中的所有行执行主体块。
$ awk 'BEGIN { FS=":";print "---header---" } \
/mail/ {print $1} \
END { print "---footer---"}' /etc/passwd /etc/group
---header---
mail
mailnull
mail
mailnull
---footer---
BEGIN
块和 END
块也只会执行一次。