【问题标题】:How to remove lines appear only once in a file using bash如何使用bash删除文件中仅出现一次的行
【发布时间】: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 awk uniq


【解决方案1】:

如果你的重复行是连续的,你可以使用uniq

uniq -D file

来自手册页:

-D 打印所有重复的行

【讨论】:

  • 如果重复行不连续,必须先排序sort file | uniq -D
  • 请注意,-DGNU 特定 扩展,不适用于 BSD/macOS uniq
【解决方案2】:

只需循环文件两次:

$ awk 'FNR==NR {seen[$0]++; next} seen[$0]>1' file file
3
3
  • 首先计算一行出现的次数:seen[ record ] 将其作为一个数组进行跟踪。
  • 其次打印出现多次的那些

【讨论】:

  • 这个答案将保留原始顺序,即使输入数据未排序,它也能正常工作++
【解决方案3】:

使用单通 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,那么我们打印这些行的次数与频率一样。

【讨论】:

【解决方案4】:

使用 awk,单遍:

$ awk 'a[$0]++ && a[$0]==2 {print} a[$0]>1' foo.txt
3
3

如果文件是无序的,由于解决方案没有缓冲值,输出将按照在文件中找到重复项的顺序发生。

【讨论】:

    【解决方案5】:

    这是一个 符合 POSIX 的 awk 替代 GNU 特定的 uniq -D

    awk '++seen[$0] == 2; seen[$0] >= 2' file
    

    结果证明这只是James Brown's helpful answer 的更短形式。

    uniq 不同,此命令严格不要求对重复项进行分组,但输出顺序只有在它们被分组时才可预测。

    也就是说,如果重复项没有分组,则输出顺序由每组重复项中的2nd个实例的相对顺序决定,并且每组中的第一个和第二个实例将一起打印。

    对于未排序(未分组)数据(如果保留输入顺序也很重要),请考虑:

    【讨论】:

    • 它更短,我会喝到那个。
    • @JamesBrown:谢谢——直到我写完我的答案之后,我才真正注意到(并且投票赞成)你的答案。
    猜你喜欢
    • 2014-07-05
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 2016-01-09
    相关资源
    最近更新 更多