grep 之后,缺一步「切列」
日志一行里有时间、级别、线程、服务名、耗时十几个字段,grep 只能把整行捞出来,awk 才能精准取出其中某一列。上篇排查四步里的第 2 步(统计时间分布)就埋了它的伏笔,现在正式登场。
$ echo "2026-03-18 10:00:01 ERROR order-svc took 1520ms" | awk '{print $4}'
ERROR
$ echo "2026-03-18 10:00:01 ERROR order-svc took 1520ms" | awk '{print $5}'
order-svc
$ echo "2026-03-18 10:00:01 ERROR order-svc took 1520ms" | awk '{print $NF}'
1520msawk 默认按连续空白切列,数字即列号:$1 第一列、$NF 最后一列、NF 总列数、NR 当前行号。这四个内置变量解决 90% 的场景。
-F:指定分隔符
$ awk -F: '{print $1, $7}' /etc/passwd # 冒号分隔:用户名 + 默认 shell
root /bin/bash
app /bin/bash
$ awk -F= '/server.port/{print $2}' application.properties # 取 key=value 的 value
9090print 里的逗号会在输出时自动补一个空格。/正则/ 放在花括号前是行过滤器——只对匹配行执行动作。
条件过滤:awk 是门语言
$ awk '$9==500' access.log # 只看第 9 列(状态码)为 500 的行
$ awk '$10>1000' access.log # 耗时大于 1000ms 的慢请求
$ awk '/ERROR/ && $NF>500' app.log # 含 ERROR 且末列数值大于 500
$ awk 'NR>1 && NR<=5' app.log # 第 2 到 5 行(跳过表头)两个字段比较时会自动按数字处理(哪怕它们看起来是字符串),&&、|| 组合条件和大多数语言一致。
统计汇总:每行累计,END 收账
# 平均耗时 = 总耗时累加 / 行数
$ awk '{s+=$10; n++} END {print s/n " ms"}' access.log
# 5xx 次数统计(c+0:一行都没有时输出 0 而不是空行)
$ awk '$9>=500 {c++} END {print c+0}' access.log{s+=$10; n++} 每读一行执行一次,END {...} 在全部读完后执行一次——用一条命令完成读文件加统计,不用再写脚本。
实战:一条命令找出访问量 Top 5 的 IP
$ awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -5
812 47.98.x.x
655 223.104.x.x
344 116.23.x.x
210 39.144.x.x
98 112.17.x.x拆解这条出场率冠军流水线:awk 取 IP 列 → sort 排序让相同值相邻 → uniq -c 去重计数 → sort -rn 按次数倒序 → head 取前五。它同时是排查刷量、爬虫、CC 攻击的第一反应,值得背下来。至此「筛行的 grep + 切列的 awk」都到手了,下一篇是三剑客的最后一剑:sed,批量修改文件的流编辑器——改配置、洗数据全靠它。
评论 (0)