如何使用正则表达式查找和删除文件中的重复行?

时间:2009-10-15 16:05:18

标签: regex

这个问题意味着与语言无关。只使用正则表达式,我可以找到并替换文件中的重复行吗?

请考虑以下示例输入和我想要的输出;

输入和GT;>

11
22
22  <-duplicate
33
44
44  <-duplicate
55

输出&GT;&GT;

11
22
33
44
55

3 个答案:

答案 0 :(得分:76)

Regular-expressions.info在Deleting Duplicate Lines From a File

上有一个页面

这基本上归结为搜索这个oneliner:

^(.*)(\r?\n\1)+$

...替换为\1
注意:Dot必须与Newline

不匹配

说明:

  

caret只会在一行的开头匹配。所以正则表达式引擎只会尝试匹配那里的正则表达式的其余部分。 dotstar组合只是匹配整行,无论其内容是什么(如果有的话)。括号将匹配的行存储到第一个反向引用中。

     

接下来,我们将匹配行分隔符。我将question mark放入\r?\n以使此正则表达式适用于Windows(\r\n)和UNIX(\n)文本文件。所以到目前为止,我们匹配了一条线和下面的换行符。

     

现在我们需要检查这个组合后面是否是同一行的副本。我们只使用\1执行此操作。这是第一个支持我们匹配的行的反向引用。反向引用将匹配相同的文本。

     

如果反向引用无法匹配,则会丢弃正则表达式匹配和反向引用,并且正则表达式引擎会在下一行的开头再次尝试。如果反向引用成功,则正则表达式中的plus symbol将尝试匹配该行的其他副本。最后,dollar symbol强制正则表达式引擎检查后向引用匹配的文本是否是完整的行。我们已经知道反向引用匹配的文本前面有一个换行符(由\ r?\ n匹配)。因此,我们现在使用dollar sign检查它是否也跟着换行符或它是否在文件的末尾。

     

整场比赛变为line\nline(或line\nline\nline等)。因为我们正在进行搜索和替换,所以从文件中删除了行,它们的副本以及它们之间的换行符。由于我们希望保留原始行,而不是重复行,因此我们使用\1作为替换文本以将原始行重新放入。

答案 1 :(得分:4)

请参阅我的更多信息请求,我现在正在简单的方式回答

  1. 如果订单无关紧要,只需

    sort -u

    会做的伎俩

  2. 如果订单确实很重要,但你不介意重新运行多次传递(这是vim语法),你可以使用:

    %S / \(。* \)\(\ _。* \)\(\ 1 \)/ \ 2 \ 1 /克

    保留最后一次出现,或

    %S / \(。* \)\(\ _。* \)\(\ 1 \)/ \ 1 \ 2 / g的

    保留第一次出现。

  3. 如果你介意重新运行多次通过,而不是更困难,那么在我们处理之前,请在问题中这样说!

    编辑:在您的编辑中,您不是很清楚,但看起来您只需要删除一次重复的ADJACENT行!嗯,这更容易!

    简单:

    /(.*)\1*/\1/
    

    (vim中的/\(.*\)\1*/\1/),即搜索(.*)\1*并将其替换为\1就行了

答案 2 :(得分:3)

在RegexBuddy中,您可以按照以下方式执行此操作:

  1. 在“库”选项卡上,如果未默认加载,则加载RegexBuddy.rbl库。
  2. 在查阅框中,键入“duplicate”
  3. 点击“使用”按钮加载“删除重复行”正则表达式。
  4. 在“GREP”选项卡上,指定要从中删除重复文件的文件夹和文件掩码。
  5. 在GREP按钮的下拉菜单中,选择执行。
  6. 如果您只在一个文件上执行此操作,则可以使用“测试”选项卡而不是“GREP”选项卡。在“测试”选项卡上加载文件,然后单击主工具栏中的“替换”按钮。