====== 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]]))