【发布时间】:2016-10-21 11:17:19
【问题描述】:
如何删除 bash 文件中仅出现一次的行?
例如,文件 foo.txt 有:
1
2
3
3
4
5
处理文件后,仅
3
3
将保留。
注意文件已经排序了。
【问题讨论】:
-
如果有数字
1,3,1,3是输出的顺序还是可以处理1,1,3,3,? -
@James Brown 文件已排序。
如何删除 bash 文件中仅出现一次的行?
例如,文件 foo.txt 有:
1
2
3
3
4
5
处理文件后,仅
3
3
将保留。
注意文件已经排序了。
【问题讨论】:
1,3,1,3是输出的顺序还是可以处理1,1,3,3,?
如果你的重复行是连续的,你可以使用uniq
uniq -D file
来自手册页:
-D 打印所有重复的行
【讨论】:
sort file | uniq -D
-D 是 GNU 特定 扩展,不适用于 BSD/macOS uniq。
只需循环文件两次:
$ awk 'FNR==NR {seen[$0]++; next} seen[$0]>1' file file
3
3
seen[ record ] 将其作为一个数组进行跟踪。【讨论】:
使用单通 awk:
awk '{freq[$0]++} END{for(i in freq) for (j=1; freq[i]>1 && j<=freq[i]; j++) print i}' file
3
3
freq[$0]++ 计算并存储每行的频率。END 块中,如果frequency 大于1,那么我们打印这些行的次数与频率一样。【讨论】:
for-loop guru approaches
使用 awk,单遍:
$ awk 'a[$0]++ && a[$0]==2 {print} a[$0]>1' foo.txt
3
3
如果文件是无序的,由于解决方案没有缓冲值,输出将按照在文件中找到重复项的顺序发生。
【讨论】:
这是一个 符合 POSIX 的 awk 替代 GNU 特定的 uniq -D:
awk '++seen[$0] == 2; seen[$0] >= 2' file
结果证明这只是James Brown's helpful answer 的更短形式。
与uniq 不同,此命令严格不要求对重复项进行分组,但输出顺序只有在它们被分组时才可预测。
也就是说,如果重复项没有分组,则输出顺序由每组重复项中的2nd个实例的相对顺序决定,并且每组中的第一个和第二个实例将一起打印。
对于未排序(未分组)数据(如果保留输入顺序也很重要),请考虑:
【讨论】: