用 awk 快速处理表格型日志:按列筛、求和与去重
服务器上的日志大多是表格型的:一行一条记录,字段之间用空格或逗号隔开,比如访问日志里的 IP、时间、状态码,或者 df 输出里的挂载点和使用率。遇到这种数据,awk 是最顺手的工具:它按行读、按列拆,不用写脚本就能做筛选、统计和去重。
1. 先看清列:默认按空白分列
awk 默认把连续的空格和制表符当成分隔符,第 1 列是 $1,第 2 列是 $2,整行是 $0。比如想从访问日志里只看 IP 和状态码:awk '{print $1, $9}' access.log。如果字段之间是逗号,比如 CSV,要先告诉它分隔符:awk -F',' '{print $1, $3}' data.csv,-F 后面就是分隔符。
动手前先用 head -5 文件名 看几行样例,确认每列到底是什么、分隔符是空格还是逗号,列数对不对。这一步花不了半分钟,却能避免后面统计结果全错。
2. 按条件筛:只留关心的行
awk 的模式写在花括号前面,满足条件的行才会执行后面的动作。想找状态码是 500 的请求:awk '$9 == 500' access.log,$9 是状态码那一列。想找某个 IP 的记录:awk '$1 == "192.168.1.10"' access.log,字符串条件要加引号。
条件可以组合:awk '$9 >= 500 && $9 < 600' access.log 找出所有 5xx 的行。先筛再统计,结果会干净很多,排查时不用在一堆无关记录里翻。
3. 求和与计数:不用导进表格也能算
awk 可以在处理每一行时累加,最后统一输出。比如统计每个状态码各出现几次:awk '{count[$9]++} END {for (c in count) print c, count[c]}' access.log,count 是按状态码分组的计数器,END 表示所有行读完后再执行。
求和同理:假设第 4 列是响应字节数,算总流量就是 awk '{sum += $4} END {print sum}' access.log。数据量不大时,这比把日志导进表格软件再求和快得多,而且结果直接落在终端里,方便接着用管道处理。
4. 去重:先排序再去重,或者用 awk 一步到位
去重最稳的组合是 sort | uniq,但 awk 也能一步做:awk '!seen[$1]++' access.log 只保留每个 IP 第一次出现的行,后面重复的直接跳过。seen 是个关联数组,记录每个值出现过几次,!seen[$1]++ 的意思是“这个值还没见过时才打印”。
要注意:awk 去重保留的是第一次出现的顺序,不排序。如果既要去重又要按次数排序,先用 awk 计数,再把结果管道给 sort -nr,按次数从大到小排,排在前面的就是最值得先看的。
5. 两个常见坑
一是列数不固定:有的行缺字段,后面的列会整体前移,统计就错位了。先用 awk '{print NF}' 文件 | sort | uniq -c 看看每行的列数是不是一致,NF 就是当前行的列数。二是分隔符里有空格:比如时间字段本身带空格,列就会被多切一刀,这时要么用 -F 指定更准确的分隔符,要么先用 sed 把时间字段处理一下再交给 awk。
记住一个顺序就够了:先看样例定列,再筛条件缩小范围,最后做统计或去重。awk 本身不改原文件,只负责读和算,查完再决定要不要动手修,操作就安全多了。
- 点赞
- 收藏
- 关注作者
评论(0)