【问题标题】:Remove duplicate lines from file从文件中删除重复的行
【发布时间】:2014-06-03 11:02:47
【问题描述】:

我有一个 URL 列表,其中大部分是重复的:

> http://example.com/some/a-test-link.html
> http://example.com/some/a-test-link.html
> http://example.com/some/another-link.html
> http://example.com/some/another-link.html
> http://example.com/some/again-link.html
> http://example.com/some/again-link.html

我不需要两次相同的链接,所以我需要删除重复的链接并只保留一个链接。如何使用正则表达式或sedawk 来做到这一点(我不确定哪种技术最好)。我使用 Ubuntu 作为操作系统,使用 Sublime Text 3 作为我的编辑器。

【问题讨论】:

  • 使用 uniq 过滤重复项可能更容易:unixhelp.ed.ac.uk/CGI/man-cgi?uniq
  • 你好@ChrisLaplante,是的,它可以使用uniq -d filename.txt newname.txt。非常感谢!但是我们如何使用正则表达式来做到这一点?只是好奇。
  • unix 工具一次处理一行数据。 uniq -d 是一种特殊情况,因为它保留前一行进行比较。 sed 可以使用正则表达式将一行与前一行进行比较,但如果您不是专家,这真的不是 sed 的设计目的。 awk 将保留上一行的副本,就像 uniq -d 一样,但您只能使用字符串比较运算符 ==,而不是正则表达式。如果您想在这方面做得更好,请阅读 O'Reilly sed and awk 的书。祝你好运。
  • @shellter,感谢您宝贵的cmets,我实际上是一个新手,边做边学!
  • 不要拿那本书sed and awk。您根本不需要一本书来了解 sed 的优点(单行上的简单替换),而 Robins 的书 Effective Awk Programming, Third Edition 更全面,更适合学习 awk。您还应该考虑约翰逊的书Shell Scripting Recipes

标签: regex awk sed sublimetext3


【解决方案1】:
$ sort -u file
> http://example.com/some/again-link.html
> http://example.com/some/another-link.html
> http://example.com/some/a-test-link.html

【讨论】:

  • 我确实在一个大文件上运行了这个,sort 用了 3 秒,awk 用了 15 秒。因此,如果速度很重要,请使用 sort +1
  • 原始文件是否已经排序可能很重要。 awk 可能在恒定时间内运行,如果输入是 [部分] 排序的,sort 可能更快。当然,如果保证输入是完全排序的,那么您只需使用uniq
【解决方案2】:

您也可以使用 sort 和 uniq 的组合:

sort input.txt | uniq

对重复的链接进行排序分组,uniq删除所有连续的重复链接。

【讨论】:

    【解决方案3】:

    这可能对你有用(GNU sed):

    sed -r 'G;/(http[^\n]*)\n.*\1/d;s/\n.*//;H' file
    

    使用保留空间保存以前看到的 URL 并删除包含重复的行。

    【讨论】:

    • 我有一个包含 50 个链接的文件。当我使用你的 sed 命令过滤我的文件链接时,我只过滤了 3 个链接,只有前 6 个链接。它忽略了该文件的其他 46 个链接。
    【解决方案4】:

    使用awk 非常简单:

    awk '!seen[$0]++' file
    

    这基本上意味着:

    awk "!($0 in seen) {seen[$0];print}"
    

    因此,如果该行不在数组中,它将添加到它并打印它。所有后续行(如果它们存在于数组中)将被跳过。

    $ cat file
    > http://example.com/some/a-test-link.html
    > http://example.com/some/a-test-link.html
    > http://example.com/some/another-link.html
    > http://example.com/some/another-link.html
    > http://example.com/some/again-link.html
    > http://example.com/some/again-link.html
    $ awk '!seen[$0]++' file
    > http://example.com/some/a-test-link.html
    > http://example.com/some/another-link.html
    > http://example.com/some/again-link.html
    

    【讨论】:

      【解决方案5】:

      不确定这是否适合您,但是,如果链接按您发布的顺序排列,则以下正则表达式将为您提供独特的结果。

      /(http:\/\/.*?)\s+(?:\1)/gm
      

      http://regex101.com/r/zB0pW3

      【讨论】:

      • 我经常看到这类帖子。您使用什么工具来处理输入文件并使用您的正则表达式创建输出文件?感谢分享。
      • @Tuga,感谢您的评论。我刚刚签入了 regex1o1,它在那里与 PCRE(PHP) 一起工作,但不知何故我无法让它与 egrep 或 sublimetext 正则表达式匹配一起工作。
      • @TamimIbrahim 我认为你应该坚持使用 JS 答案。
      猜你喜欢
      • 1970-01-01
      • 2018-01-31
      • 2010-11-17
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      相关资源
      最近更新 更多