begin 和 end 块分别在 awk 处理输入前和处理后执行,用于初始化和汇总;begin 适合设分隔符、打印表头,end 用于统计输出;二者共用变量,且语法中各只能出现一次。

awk 的 BEGIN 和 END 块是控制执行时机的关键机制,它们不依赖输入行,而是分别在处理前和处理后固定触发,让 awk 不仅能逐行分析,还能做初始化和汇总。
BEGIN 块:处理前一次性执行
它在 awk 读取任何输入行之前运行,适合做变量初始化、设置分隔符、打印表头等准备动作。
- 用
FS或OFS修改字段分隔符比命令行-F更灵活,比如:awk 'BEGIN{FS=":"; OFS=" | "} {print $1,$3,$7}' /etc/passwd - 输出表头时避免与数据混在一起,例如统计用户信息前加标题:
awk -F: 'BEGIN{print "User\tUID\tShell"} {print $1,$3,$7}' /etc/passwd - 可以单独测试,无需输入文件:
awk 'BEGIN{print "Hello", 2+3}'直接输出Hello 5
END 块:所有行处理完再执行
它在最后一行读完、所有匹配动作完成后运行,常用于输出统计结果、累加值或收尾提示。
- 统计匹配行数,比如统计含
/bin/bash的用户数量:awk -F: '/\/bin\/bash$/ {count++} END{print "Total:", count+0}' /etc/passwd
(+0确保未匹配时输出0) - 计算某列总和,如日志中第 3 列为响应时间:
awk '{sum += $3} END{print "Avg:", sum/NR}' access.log - 配合 BEGIN 初始化,形成完整流程:
awk 'BEGIN{max=0} $1>max{max=$1} END{print "Max value:", max}' numbers.txt
BEGIN 和 END 配合使用的典型结构
一个清晰的 awk 脚本通常按“准备—处理—收尾”三段组织,中间可嵌入任意数量的模式动作块。
- 语法顺序固定:
BEGIN{...} pattern{...} pattern{...} END{...} - 多个 BEGIN 或 END 不合法,每个脚本最多一个 BEGIN 块和一个 END 块
- 它们之间可共用变量,比如在 BEGIN 中定义计数器,在正则匹配块中递增,在 END 中输出
- 实际例子:带格式的 IP 访问统计
awk 'BEGIN{print "IP Count"} {ip[$1]++} END{for (i in ip) print i, ip[i]}' access.log
注意事项和常见误区
看似简单,但容易因执行顺序或变量作用域出错。
- BEGIN 中不能访问
$1、NF等字段相关变量,因为尚未读入任何行 - END 中无法使用
NR判断是否处理过数据?其实可以——NR在 END 中已为总行数,但若输入为空,NR为 0 - 不要在 END 块里写
print $0,此时$0为空;要输出汇总结果,就得靠提前累计的变量 - 如果同时用了
-v定义变量和 BEGIN 块,-v优先级更高,会在 BEGIN 执行前赋值











