这个问题意味着与语言无关。只使用正则表达式,我可以找到并替换文件中的重复行吗?
请考虑以下示例输入和我想要的输出;
输入和GT;>
11
22
22 <-duplicate
33
44
44 <-duplicate
55
输出&GT;&GT;
11
22
33
44
55
答案 0 :(得分:76)
Regular-expressions.info在Deleting Duplicate Lines From a File
上有一个页面这基本上归结为搜索这个oneliner:
^(.*)(\r?\n\1)+$
...替换为\1
。
注意:Dot必须与Newline
说明:
caret只会在一行的开头匹配。所以正则表达式引擎只会尝试匹配那里的正则表达式的其余部分。 dot和star组合只是匹配整行,无论其内容是什么(如果有的话)。括号将匹配的行存储到第一个反向引用中。
接下来,我们将匹配行分隔符。我将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)
请参阅我的更多信息请求,我现在正在简单的方式回答。
如果订单无关紧要,只需
sort -u
会做的伎俩
如果订单确实很重要,但你不介意重新运行多次传递(这是vim语法),你可以使用:
%S / \(。* \)\(\ _。* \)\(\ 1 \)/ \ 2 \ 1 /克
保留最后一次出现,或
%S / \(。* \)\(\ _。* \)\(\ 1 \)/ \ 1 \ 2 / g的
保留第一次出现。
如果你介意重新运行多次通过,而不是更困难,那么在我们处理之前,请在问题中这样说!
编辑:在您的编辑中,您不是很清楚,但看起来您只需要删除一次重复的ADJACENT行!嗯,这更容易!简单:
/(.*)\1*/\1/
(vim中的/\(.*\)\1*/\1/
),即搜索(.*)\1*
并将其替换为\1
就行了
答案 2 :(得分:3)
在RegexBuddy中,您可以按照以下方式执行此操作:
如果您只在一个文件上执行此操作,则可以使用“测试”选项卡而不是“GREP”选项卡。在“测试”选项卡上加载文件,然后单击主工具栏中的“替换”按钮。