3

问题是什么:

我有一个多行文本,例如:

1: This is test string for my app. d
2: This is test string for my app.
3: This is test string for my app. abcd
4: This is test string for my app.
5: This is test string for my app.
6: This is test string for my app.
7: This is test string for my app. d
8: This is test string for my app.
9: This is test string for my app.
10: This is another string.

行号在这里只是为了更好地可视化,它们不是文本本身的一部分。

我试过的:

我尝试了两种不同的正则表达式(标志总是:i gm):

^([^\r\n]*)$(.*?)(?:(?:\r?\n|\r)\1)+$

见这里:regexr.com/5nklg

^(.*)(?:\r?\n|\r)(?=[\s\S]*^\1$)

见这里:regexr.com/5nkla

它们都产生不同的输出,都很好,但并不完美。

我想达到的目标:

删除文本中所有重复的短语,但保留一个。所以这里例如保留第一个“这是我的应用程序的测试字符串”。从第 1 行开始,匹配第 2-9 行的相同短语并保留第 10 行。

如果我可以保留最后一个而不是第一个匹配的短语,它也会对我有用。所以这里将匹配第 1 - 8 行,保留 9 和 10。

有没有办法用正则表达式做到这一点?

仅供参考:稍后我将在 python 中使用正则表达式来删除重复项:

re.sub(r"^(.*)(?:\r?\n|\r)(?=[\s\S]*^\1$)", "", my_text, flags=re.MULTILINE)

编辑: “短语”意味着让我们说 3 个或更多单词。所以匹配任何超过 2 个单词的重复项。所以第一个子之后的预期输出将是:

This is test string for my app. d  //from line 1
This is test string for my app.    //from line 2
abcd                               //from line 3
This is another string.            //from line 10

提前致谢!

4

1 回答 1

2

您可以使用

re.sub(r'^(([^\n\r.]*).*)(?:(?:\r?\n|\r)\2.*)*', r'\1', my_text, flags=re.M)

请参阅正则表达式演示

详情

  • ^- 行的开始(由于re.M使用了该选项,^现在匹配行的开始位置)
  • (([^\n\r.]*).*)- 第 1 组:除点之外的零个或多个字符,CR 和 LF 被捕获到第 2 组,然后是该行的其余部分
  • (?:(?:\r?\n|\r)\2.*)*- 零个或多个序列
    • (?:\r?\n|\r)- CRLF、CR 或 LF 行尾
    • \2- 与第 2 组中的相同文本
    • .*- 线路的其余部分。

替换是第 1 组值。

于 2021-03-02T21:03:04.547 回答