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 块也只会执行一次。