awk文本统计核心是“数据结构→字段提取→逻辑聚合→结果输出”主线,需先确认分隔符与字段位置,用关联数组计数,BEGIN/END控制流程,结合过滤和字符串操作提升精度。

用 awk 写复杂文本统计脚本,关键不是堆砌语法,而是理清“数据结构→字段提取→逻辑聚合→结果输出”这条主线。它本质是面向行、按列处理的轻量级数据流水线,不需要写函数也能完成多数统计任务。
明确字段分隔与目标字段
多数统计失败,源于没先确认分隔符和字段位置。比如处理 /etc/passwd,必须用 -F:;处理 CSV 日志,得用 -F',';若字段含空格又混杂制表符,可用 -F'[[:space:]]+' 或 BEGIN{FS="\s+"}。打印前先试跑:awk -F: '{print NF, $1, $7}' /etc/passwd | head -3,确认字段数和内容是否符合预期。
用数组做计数与分组聚合
awk 的关联数组是统计核心,语法简洁:count[$key]++ 即可累加。常见模式包括:
- 按 IP 统计次数:
awk '{ip[$1]++} END {for (i in ip) print i, ip[i]}' access.log - 按状态码+IP 联合统计:
awk '{key = $1 " " $9; cnt[key]++} END {for (k in cnt) print k, cnt[k]}' access.log - 统计某字段出现频次并限制输出:
awk '{a[$3]++} END {for (i in a) if (a[i] > 5) print i, a[i]}' data.txt
用 BEGIN/END 控制流程与格式化输出
BEGIN 块适合初始化变量、打印表头;END 块负责汇总、排序、格式对齐。例如生成带标题的 shell 类型统计:
awk -F: 'BEGIN {printf "%-15s %s ", "Shell", "Count"} {sh[$7]++} END {for (s in sh) printf "%-15s %d ", s, sh[s]}' /etc/passwd- 若需按数量降序排列,可在 END 块后接管道:
... END {for (s in sh) print sh[s], s}' | sort -nr | cut -d' ' -f2-
嵌入条件与字符串操作提升精度
真实日志常含注释、空行、非标准格式,需前置过滤。常用手段有:
- 跳过注释和空行:
NR > 0 && !/^#/ && NF > 0 - 安全转数字(防字符串比较):
$5+0 > 80比$5 > "80%"更可靠 - 提取子串或标准化内容:
substr($4,2,11)截取时间字段,toupper($2)统一大小写 - 正则匹配筛选:
$9 ~ /^2|3[0-9]{2}$/匹配成功 HTTP 状态码
不复杂但容易忽略:awk 脚本越长,越要善用单引号包裹、避免 shell 变量提前展开;多文件处理注意 FNR 和 NR 区别;大文件统计时,END 块内遍历数组无需排序,交给 sort 更高效。


















