====== AWK 入门介绍 ======
AWK 是 Unix/Linux 上诞生于 1970 年代的文本处理工具,名字取自三位作者 Aho、Weinberger、Kernighan 的姓氏首字母。它既不是一门独立的编程语言,也不是 sed 的替代品——它的核心能力在于 **按行读取、按模式匹配、按字段处理结构化文本**。(([[https://en.wikipedia.org/wiki/AWK|AWK - Wikipedia]]))
===== 核心概念:模式-动作 =====
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'' 可处理段落式数据。(([[https://www.gnu.org/software/gawk/manual/gawk.html#Multiple-Line|RS="" 分块处理(gawk 手册)]]))
用 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 能让日志分析、数据清洗、报表生成等日常运维工作效率提升一个档次。(([[https://www.gnu.org/software/gawk/manual/gawk.html|GNU Awk 用户手册]]))(([[https://www.amazon.com/AWK-Programming-Language-Alfred-Aho/dp/020107981X|《The AWK Programming Language》]]))(([[https://catonmat.net/awk-one-liners-explained-part-one|AWK One-Liners Explained]]))