做什么
awk = 按列处理 + 简单脚本语言。自动把每行切分成 $1 $2 $3 ... 列。
核心:列处理
awk '{print $1}' file.txt # 第 1 列
awk '{print $1, $3}' file.txt # 第 1 和 3 列
awk '{print $NF}' file.txt # 最后一列
awk '{print NR, $0}' file.txt # 行号 + 整行
内置变量
| 变量 | 含义 |
|---|---|
$0 |
整行 |
$1 $2 ... |
第 N 列 |
$NF |
最后一列 |
NF |
当前行的列数 |
NR |
当前行号(从 1 起) |
FS |
输入分隔符(默认空白) |
OFS |
输出分隔符 |
条件过滤
awk '$3 > 100' data.txt # 第 3 列 > 100 的行
awk '/ERROR/ {print $1}' app.log # 含 ERROR 的行打印第 1 列
awk '$2 == "200"' access.log # 第 2 列等于 "200"
awk 'NR >= 10 && NR <= 20' file.txt # 第 10-20 行
自定义分隔符
awk -F',' '{print $2}' data.csv # CSV:逗号分隔
awk -F':' '{print $1}' /etc/passwd # /etc/passwd 用 : 分隔
awk 'BEGIN{FS=","; OFS="\t"} {print $1, $3}' data.csv
BEGIN / END
awk 'BEGIN{print "header"} {print} END{print "total:", NR}' file.txt
BEGIN{} 处理前跑一次,END{} 处理完跑一次——很适合做汇总。
实战:常见统计
# 求和(第 1 列)
awk '{sum += $1} END {print sum}' nums.txt
# 平均值
awk '{sum += $1; n++} END {print sum/n}' nums.txt
# 最大值
awk '$1 > max {max = $1} END {print max}' nums.txt
# 分组计数(按第 2 列分组)
awk '{count[$2]++} END {for (k in count) print k, count[k]}' data.txt
# Nginx 日志:最热 IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
# Nginx 日志:每个状态码的次数
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 看 /etc/passwd 里能登录的用户
awk -F: '$7 != "/usr/sbin/nologin" {print $1}' /etc/passwd
坑
- awk 的列分割按"空白"是默认行为,但多个连续空格当一个分隔符——CSV 等场景必须
-F - 大文件 awk 比 sed/grep 慢——简单任务不要用 awk
- gawk(GNU awk)和 mawk(mini awk)行为略不同——脚本里跨平台要小心