【问题标题】:Regex to remove double lines ignoring the punctation marks and spaces in Notepad++ [duplicate]正则表达式删除双行忽略记事本++中的标点符号和空格[重复]
【发布时间】:2022-08-13 08:01:07
【问题描述】:

是否可以通过忽略 Notepad++ 中的标点符号和空格来删除重复项?我会保留其中一个匹配的行(保留哪个无关紧要)。

我的示例来自 txt 文件:

Rough work iconoclasm but the only way to get the truth. Oliver Wendell Holmes
Rough work, iconoclasm, but the only way to get the truth. Oliver Wendell Holmes

Rule No. 1: Never lose money. Rule No. 2: Never forget rule No. 1. Warren Buffett
Rule No.1: Never lose money. Rule No.2: Never forget rule No.1. Warren Buffett

Self-esteem isn\'t everything, it\'s just that there\'s nothing without it. Gloria Steinem 
Self-esteem isn\'t everything it\'s just that there\'s nothing without it. Gloria Steinem

You said she\'s a senior? Babe we\'re all crazy.
You said, she\'s a senior! Babe we\'re ALL crazy.
You said, she\'s a senior? Babe we\'re ALL crazy!

结果我需要:

Rough work iconoclasm but the only way to get the truth. Oliver Wendell Holmes

Rule No. 1: Never lose money. Rule No. 2: Never forget rule No. 1. Warren Buffett

Self-esteem isn\'t everything, it\'s just that there\'s nothing without it. Gloria Steinem 

You said, she\'s a senior! Babe we\'re ALL crazy.

我可以使用正则表达式删除 100% 匹配的重复项,但找不到忽略空格和标记的正则表达式规则。

  • 是的,重复的行总是连续的,因为我首先对行进行排序。

标签: regex text duplicates notepad++


【解决方案1】:

我不认为正则表达式是完成这项任务的最佳工具,但这是一个很好的挑战。您可以使用嵌套结构匹配单个单词,例如:

((\w+)\W+((\w+)\W+( ... ((\w+)\W+)? ... )?)?(\w*))

匹配时,捕获组 2 到 n 包含一行的单词 1 到 n-1。嵌套结构对于使其不模糊是必要的 - 否则,运行正则表达式需要太长时间。

为了匹配重复的行,我们使用带有反向引用的类似结构:

\1\W+(\2\W+( ... (\9\W+)? ... )?)?

这也将匹配作为前一行子字符串的行,这再次有助于提高性能。

请注意,当using more than 9 references in Notepad++ 时,您必须使用\g{n} 表示法。此外,为避免匹配换行符,您应该使用[^\w\n\r] 而不是\W。为了进一步提高性能,不必要的组应该是不匹配的,即(?: ... )

要生成解决问题的相当长的正则表达式,例如每行最多 20 个单词,您可以使用以下脚本:

MAX_WORDS = 20
punct = "[^\\w\\n\\r]"
backref = (i) => `\\g{${i}}`
patternKeep = (i) => "(\\w+)[^\\w\\n\\r]+" + (i < 0 ? "" : `(?:${patternKeep(i-1)})?`)
patternRemove = (i) => `${backref(MAX_WORDS-i + 2)}(?:${punct}+` + (i < 0 ? "" : patternRemove(i-1)) + ")?"
console.log("^(" + patternKeep(MAX_WORDS) + "(\\w*))(\\r?\\n" + patternRemove(MAX_WORDS)+ `${punct}*${backref(MAX_WORDS+4)}${punct}*)+$`)

将其复制到 Notepad++ 并设置“环绕”并关闭“匹配大小写”并替换为 $1 时,它将删除示例中的所有重复行。

【讨论】:

  • 谢谢! ?不确定,但看起来像is an issue。我用✖标记了那些(相同的开始,但更短/没有重复恕我直言)。顺便提一句。我也认为正则表达式不太适合这项任务,但就像你说的那样具有挑战性。
  • 是的,这就是我所说的“它也匹配子字符串”的意思。根据我的想法,这简化了正则表达式并使其运行得更快,这似乎是一种妥协,对于这种正则表达式的大多数应用程序来说都是可以的。
【解决方案2】:

我怀疑它可以纯粹用正则表达式来完成。如果可以,那么我想该表达式将难以理解且难以维护。相反,我建议采用多步骤方法。

步骤 1 - 将每一行修改为: original-line separator original-line。

第 2 步 - 将其转换为 line-without-punctuation separator original-line。

第 3 步 - 对行进行排序

第 4 步 - 删除重复的行

第 5 步 - 删除没有标点符号的行和分隔符,只留下原始行。

更详细地说:

在下面的所有替换中:选择“环绕”,取消选择“点匹配换行符”,取消选择“仅匹配整个单词”并取消选择“匹配大小写”。

第 1 步 - 选择一个分隔符,一些不是标点符号且不会出现在文件中的文本。这里我使用qqq。用\1qqq\1 替换^(.+)$ 的正则表达式。

第 2 步 - 删除分隔符之前的所有标点符号。反复用 \1[!',-.:?]+(.*qqq) 进行正则表达式替换,直到不再进行替换。此表达式匹配示例中的所有标点符号,但您可能需要为全文添加更多内容。还需要将多个空格减少为单数,因此重复将 +(.*qqq) 替换为 \1 的正则表达式,直到不再进行替换。在qqq 之前处理空格的最后一步是用qqq qqq 进行正则表达式替换(这也可以使用非正则表达式替换)。

第 3 步 - 按字典顺序对行进行排序。

第 4 步 - 删除重复的行。反复用\1^(.*qqq).*\R\1 进行正则表达式替换,直到不再进行替换。

第 5 步 - 删除不需要的文本,留下原始行。用正则表达式替换 ^.*qqq 什么都没有(空字符串)。


如果可以删除所有标点符号并且结果是没有标点符号的行,那么可以简单地将[!',-.:? ]+ 替换为 ,进行排序,最后删除重复项。

【讨论】:

  • 感谢您提供有趣的答案!我刚刚在顶部添加了一条评论,假设重复的行是连续的(如 OP 的示例中所示)。就像您提到的那样,当然不可能仅一步就对重复行进行排序和删除。
【解决方案3】:

我想用赏金来奖励一个有趣的答案,但是一旦我放置它,答案就被删除了。对我来说,这很有趣,因为说明了一种特殊的技术。在评论中,回答者将我指向another thread 以了解更多信息。

在对(尚未删除的)答案进行了一些试验之后,一个想法是以下模式。 NP++ 中的设置是取消选中:[ ] 匹配大小写,[ ] .matches 换行 - 替换为空字符串。

^(?>[^\w\n]*(\w++)(?=.*\R(\2?+[^\w\n]*\1\b)))+[^\w\n]*\R(?=\2[^\w\n]*$)

Here is the demo in Regex101 - 假设是,重复的行是连续的(如样本)。

很抱歉给任何人带来不便,非常感谢您提供其他有趣的解决方案。因为答案不再在这里,而赏金是为了奖励我可以从中学习的这个答案,所以我决定以客人的身份发帖。

大多数使用的正则表达式标记都可以在Stack Overflow Regex FAQ 中查找。


简而言之,使用的机制是将capture的话从一行到第一组(\w++) 而在 lookahead (?=.*\R(\2?+...\1\b))) a第二组在连续的行中是从自身“增长”加上捕获,直到\R(?=\2...$) 它匹配所有单词或失败。

来自regex101 debugger: 的一些步骤的插图

第二组保存与前一行的单词和顺序匹配的连续行的子字符串。它在每次重复时从optionally 本身和上一行中的一个单词开始扩展。由 [^\w\n]* any amount 分隔的字符 not word characters 或换行符。

为了使它工作,匹配在关键点完成without giving back(防止回溯)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 2014-06-06
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多