【问题标题】:Regex to identify consecutive and non-consecutive duplicate words in multiline text正则表达式识别多行文本中的连续和非连续重复词
【发布时间】:2020-06-22 10:50:37
【问题描述】:

我正在为具有关键字和逗号(分隔)/分号(EOL)分隔值的文件编写语法检查器(在 Java 中)。两个完整结构之间的空格数量未指定。

需要什么:

在多行文件中查找任何重复的单词(连续的和不连续的)。

// Example_1 (duplicate 'test'):
item1  , test, item3   ;
item4,item5;
test , item6;

// Example_2 (duplicate 'test'):
item1  , test, test   ;
item2,item3;

我已尝试应用 (\w+)(s*\W\s*\w*)*\1 模式,但无法正确捕获重复项。

【问题讨论】:

  • 即使它们被多个非单词字符分隔,您是否考虑重复?喜欢word \n\t--- word?或者在检查重复的单词之间是否应该只存在严格的[whitespace*][nonword][whitespace*]
  • 不连续的意思是item1, item1不应该匹配吗?
  • @Alex 查看我更新的答案,如果有连续的欺骗,则不匹配
  • 假设字符串是”a, a, a”。是只匹配第一个词还是同时匹配第一个词和第二个词(容易得多)?
  • @Cary Swoveland 在完美的情况下,我想匹配第一个副本,因为它会使错误处理(需要报告第一个副本的位置)更容易。

标签: java regex


【解决方案1】:

您可以将此正则表达式与模式 DOTALL(单行)一起使用:

(?s)(\b\w+\b)(?=.*\b\1\b)

RegEx Demo

正则表达式详细信息:

  • (?s):开启DOTALL模式
  • (\b\w+\b):匹配一个完整的单词并在#1组中捕获它
  • (?=.*\b\1\b):提前断言我们在前面的某个地方有反向引用\1\b 用于确保我们再次匹配完全相同的单词。

另外:

基于下面的早期 cmets,如果意图不匹配连续的单词重复,如 item1 item1,则可以使用以下正则表达式:

(?s)(\b\w+\b)(?!\W+\1\b)(?=.*\b\1\b)

RegEx Demo 2

这里有一个额外的否定前瞻断言,以确保我们不匹配连续重复。

  • (?!\W+\1\b):负前瞻使匹配失败连续重复。

【讨论】:

  • 这不也能捕捉到连续的重复吗?我认为它需要像(?s)(\b\w+\b)(?=.*\b\w+\b.*\b\1\b) 这样才能符合非连续重复规则。
  • @anubhava 正确
  • @anubhava 我相信这也是可以分享的有用信息。您可以将其编辑为更多读者的额外案例。
  • 好的,谢谢 Alex,这是一个很好的建议(已更新)。
  • 我很抱歉。我一定用过你的第二个正则表达式。
【解决方案2】:

你可以使用

\b(\w+)\b(?:\s*[^\w\s]\s*\w+)+\s*[^\w\s]\s*\b\1\b

regex demo

详情

  • \b(\w+)\b - 第 1 组:一个或多个单词字符作为一个完整的单词
  • (?:\s*[^\w\s]\s*\w+)+ - 1 次或多次出现:
    • \s* - 0+ 个空格
    • [^\w\s] - 1 个字符而不是单词和空格字符
    • \s* - 0+ 个空格
    • \w+ - 1+ 个单词字符
  • \s* - 0+ 个空格
    • [^\w\s] - 1 个字符而不是单词和空格字符
    • \s* - 0+ 个空格
  • \b\1\b - 与第 1 组中的值相同。

要只匹配单词,请将正则表达式的第二部分放入正向前瞻中:

\b(\w+)\b(?=(?:\s*[^\w\s]\s*\w+)+\s*[^\w\s]\s*\b\1\b)
         ^^^                                        ^

this regex demo

Java 正则表达式变量声明:

String regex = "\\b(\\w+)\\b(?:\\s*[^\\w\\s]\\s*\\w+)+\\s*[^\\w\\s]\\s*\\b\\1\\b";

要使其完全支持 Unicode,请添加 (?U):

String regex = "(?U)\\b(\\w+)\\b(?:\\s*[^\\w\\s]\\s*\\w+)+\\s*[^\\w\\s]\\s*\\b\\1\\b";

【讨论】:

  • 如果字符串是“ item1 , test, item1, test, item1;”,则只有第一个“item1”(不是“test”)与您的第一个正则表达式匹配。这与您对问题的理解一致吗?
  • @CarySwoveland OP 需要验证。如果匹配,则字符串无效。当然是排队。
  • 你觉得用 [\W] 代替 [^\w\s] 怎么样?
  • Wiktor,但 OP 的任务是“查找任何重复的单词...”。
  • @J-Alex \W 也匹配空格。
猜你喜欢
  • 1970-01-01
  • 2021-03-03
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
相关资源
最近更新 更多