目录

AWK 入门介绍

AWK 是 Unix/Linux 上诞生于 1970 年代的文本处理工具,名字取自三位作者 Aho、Weinberger、Kernighan 的姓氏首字母。它既不是一门独立的编程语言,也不是 sed 的替代品——它的核心能力在于 按行读取、按模式匹配、按字段处理结构化文本。1)

核心概念:模式-动作

AWK 程序的骨架是:

''pattern { action }''

逐行扫描输入,当某行匹配 pattern 时执行对应的 action。省略 pattern 则每行都执行;省略 { action } 则等价于 { print }(打印整行)。

最简单的例子——打印文件每一行:

awk '{ print }' /etc/passwd

字段分割

AWK 默认以空白(空格/Tab)分割每行为字段,用 $1、$2、… $NF 引用各字段。$0 代表整行。这是 AWK 区别于 sed 的核心特征——它能直接操作表格状数据。

打印第三列(比如 /etc/passwd 的用户 ID):

awk -F: '{ print $3 }' /etc/passwd

-F: 指定冒号为分隔符。也可以在内置变量 FS 中设置。

常用场景

筛选行——只打印符合条件的行:

awk '$3 > 1000 { print $1, $3 }' /etc/passwd

统计——求某列的和/平均值:

awk '{ sum += $1 } END { print sum }' numbers.txt

格式化输出——用 printf 控制输出格式:

awk '{ printf "%-20s %s\n", $1, $3 }' data.txt

内置变量

变量 含义
FS 字段分隔符(默认空白)
OFS 输出字段分隔符(默认空格)
RS 记录分隔符(默认换行)
ORS 输出记录分隔符(默认换行)
NR 当前行号
NF 当前行的字段数
$0 整行内容
$1..$NF 各字段

改变 FS/OFS 即可在不同格式之间做转换。例如把 /etc/passwd 的冒号分隔转成 CSV:

awk 'BEGIN { FS=":"; OFS="," } { print $1, $3, $5 }' /etc/passwd

BEGIN 与 END 特殊模式

BEGIN 在第一行处理前执行,适合设置变量、打印表头。END 在所有行处理完后执行,适合输出汇总结果。

awk 'BEGIN { print "用户,ID" }
     { print $1 "," $3 }
     END { print "共" NR "行" }' FS=":" /etc/passwd

关联数组

AWK 的数组是关联数组(类似 Python 的 dict),键可以是任何字符串。这是 AWK 处理分组统计的核心能力。

统计每个用户 Shell 的出现次数:

awk -F: '{ shells[$NF]++ }
     END { for (s in shells) print s, shells[s] }' /etc/passwd

RS="" 特殊模式:分块处理

这是 AWK 中最容易被忽略但极其强大的特性。当 RS=“”(空字符串)时,AWK 的分隔逻辑变为 按空行分块,每个块是一个「多行记录」。配合 FS 可处理段落式数据。2)

用 RS=“” 分块提取年龄:

awk 'BEGIN { RS=""; FS="\n" }
     { for (i=1; i<=NF; i++)
         if ($i ~ /年龄/)
           print $i }' data.txt

这个模式在处理日志分段、配置文件块、SQL 结果集时的效果远超逐行 grep。

综合示例

统计 Web 日志中各 IP 的请求次数,按降序输出前 10:

awk '{ ips[$1]++ }
     END { for (ip in ips)
             print ips[ip], ip
         }' access.log | sort -rn | head -10

总结

AWK 的定位介于 grep(纯行匹配)和 Python/Perl(全功能脚本)之间:它比 grep 更擅长结构化字段操作,又比脚本语言更适合一行命令式的快速分析。掌握 AWK 能让日志分析、数据清洗、报表生成等日常运维工作效率提升一个档次。3)4)5)