uniq只能去重相邻重复行,不排序直接使用无效;真正全文去重需先sort再uniq,或用sort -u;保持原序去重须用awk '!seen[$0]++'等内存型工具。

uniq 只能去重相邻重复行,不排序直接用等于白干。
为什么 uniq 有时完全没效果?
常见错误现象:文件里明明有重复行,运行 uniq file.txt 后输出和原文件一模一样。
根本原因:uniq 默认只比较并删除「连续重复的相邻行」,它不扫描全文、不建哈希表、也不排序——它只是从头到尾扫一遍,把紧挨着的重复行压成一行。
- 如果重复行分散在不同位置(比如第2行和第15行相同),
uniq完全无视 - 如果文件未按字典序或自然顺序排列,重复项大概率不相邻
- 想真正去重全文,必须先
sort,再uniq,或直接用sort -u
sort -u 和 sort | uniq 有什么区别?
两者功能等价,但 sort -u 更简洁、更常用,且部分老版本 uniq 不支持 -u 以外的选项(如 -c 计数)。
-
sort file.txt | uniq:显式分两步,便于加中间处理(比如先awk '{print $1}'再去重) -
sort -u file.txt:一步到位,性能略优,语义更清晰 - 注意:
sort -u输出是排序后的结果;如果需要保持原始顺序,得用其他方法(比如awk '!seen[$0]++')
怎么保留原始顺序去重?
当重复行存在、又不能打乱原有顺序时,uniq 和 sort 都不适用——必须靠 awk 或 perl 这类带内存状态的工具。
-
awk '!seen[$0]++' file.txt:最常用,逐行读取,用关联数组记录是否见过该行 -
perl -ne 'print unless $seen{$_}++':行为一致,适合已有 Perl 环境的场景 - 注意:
$0是整行,含换行符;若要去掉行首/行尾空格影响,得先gsub(/^[ \t]+|[ \t]+$/, "") - 大文件慎用:所有唯一行会暂存内存,几 GB 的日志可能 OOM
去重时忽略大小写或特定字段怎么办?
uniq 本身支持简单选项,但能力有限;复杂逻辑仍推荐 awk。
- 忽略大小写:
sort -f file.txt | uniq -i(-f排序时忽略大小写,-i去重时也忽略) - 按第一列去重:
sort -k1,1 file.txt | uniq -w N不可靠,应改用awk '!seen[$1]++' - 按制表符分隔的第3列去重:
awk -F'\t' '!seen[$3]++' file.txt -
uniq -w只截取前 N 字符比较,不按字段切分,容易误判
最容易被忽略的是:去重前到底要不要 sort,取决于你到底要“去相邻重复”还是“去全文重复”。前者用 uniq 本身即可,后者绕不开排序或哈希。别光记命令,先想清楚需求本质。










