频次统计的流水线
uniq 只能识别相邻的重复行,所以统计频次的标准流水线是:先提取待统计字段,用 sort 让相同值相邻,再用 uniq -c 计数,最后用 sort -rn 按计数降序取前几名。这条管道是统计 IP、状态码、URL、错误类型的通用套路,写法固定但每一步都有踩坑点:少了 sort 结果就完全错误,忘了 -n 会得到字典序排名,取列时又容易把计数列当成原值。数据量大时还可以先用 awk 预聚合来减少排序压力。
基本信息
| 适用平台 | Linux/macOS(GNU coreutils 与 BSD uniq/sort) |
|---|---|
| 命令语法 | uniq [-c|-d|-u] [输入] |
| 常用选项 | -c 显示计数 -d 只显示重复行 -u 只显示不重复行 -i 忽略大小写 -f N 跳过前 N 个字段 |
| 标准流水线 | 提取字段 → sort → uniq -c → sort -rn → head |
| 性能提示 | 机器数据加 LC_ALL=C 排序更快且行为一致 |
典型使用场景
- 攻击面分析:统计访问日志的 Top IP,判断是否有扫描或撞库
- 接口排行:统计最常被请求的 URL,识别热点与异常接口
- 错误分布:统计错误类型出现次数,按频次决定修复优先级
- 重复检查:找出重复的配置项或重复记录
- 去重清洗:给数据做一次简单去重
常用示例
常用示例
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20
cut -d' ' -f9 access.log | sort | uniq -c | sort -rn | head
grep -o 'ERROR [a-z_]*' app.log | sort | uniq -c | sort -rn | head
sort access.log | uniq -d | head # 只显示重复出现的行
awk '{a[$1]++} END{for(k in a) print a[k], k}' access.log | sort -rn | head # 预聚合
LC_ALL=C sort urls.txt | uniq -c | sort -rn | head管道各步作用
| 步骤 | 作用 | 常见错误 |
|---|---|---|
| 提取字段 | 用 awk 或 cut 取出待统计的列 | 列号写错会让统计对象整体错位 |
| sort | 让相同取值相邻 | 漏掉这一步,uniq 的结果不可用 |
| uniq -c | 去重并给出每项出现次数 | 计数在第 1 列,后续取列要算清楚 |
| sort -rn | 按计数降序排列 | 忘写 -n 得到字典序,10 会排在 9 前面 |
| head -N | 只保留前 N 名 | 与带颜色或表头的输出混用会污染统计 |
uniq -c 的输出是计数在前、值在后。如果后续还要对这个值再加工,注意它是第 2 列,直接沿用原来的字段序号会取到数字。
数据量很大时,可以先在 awk 里用数组完成一次聚合,再对聚合结果排序,输入行数会大幅减少,整体耗时更低。