【问题标题】:Java 8 regex: a capturing group in a pattern doesn't match, yet the whole pattern does matchJava 8 正则表达式:模式中的捕获组不匹配,但整个模式匹配
【发布时间】:2020-01-29 16:38:08
【问题描述】:

这是我的第一个问题。很高兴与大家见面。

我在 Java 8 中创建了以下正则表达式模式(为了清楚起见,这只是我在代码中实际拥有的一个简化示例):

(?<!a)([0-9])\,([0-9])(?!a)|(?<!b)([0-9]) ([0-9])(?!b)|(?<!c)([0-9])([0-9])(?!c)

所以一般来说它由三个选项组成: 第一个匹配用逗号分隔的两个单个数字,例如:

1,1
2,0
4,5

第二个匹配两个用空格分隔的单个数字,例如:

1 1
2 0
4 5

第三个匹配一行中的两个单个数字,例如:

11
20
45

每个替代方案都使用环视,并且每个替代方案的内容都必须略有不同 - 这就是为什么我不能像这样把所有东西放在一起:

([0-9])[, ]?([0-9])

每个匹配的数字都包含在一个捕获组中,现在我有第二行来“调用”这些捕获的数字,如下所示:

(?<!n)($1 $2|$3 $4|$5 $6)(?!n)

所以最后我需要匹配一个文本,该文本将具有相同的数字,用单个空格分隔并且不被“n”包围。因此,如果上面显示的任何示例与第一行的模式匹配,则第二行模式应该匹配这些:

1 1
2 0
4 5
11 11
22 00
44 55 

这些都不是:

n1 1
2,0
45
asd asd asd

问题如下:即使我在测试文本中没有这些捕获的数字,它也会返回匹配项,但我确实有空格...所以这里我没有得到匹配,这是正确的:

aaaaaaaaa
bbbbbbbbb
aasdfasdf

但在这里我得到了以下内容的匹配(最明显的是因为有一个/多个空格):

abc abc
q w r t y
as df

有谁知道这是否正常,尽管捕获组中的字符没有被第一行捕获,但“非捕获组”部分(因此单个空格)将被匹配,因此整个模式返回匹配,如果第一行没有捕获任何内容,就好像捕获组可能是第二行中的零长度匹配?提前感谢您对此发表任何评论。

【问题讨论】:

  • 我认为简化的正则表达式没有任何问题(除了它是一个正则表达式,而且是一个非常复杂的 :) )。编码的正则表达式中可能有错字,所以如果你想要答案,请出示。但最好使用 String.split 和 Integer.parseInt 或其他简单易读的东西来解决您的任务。否则,您将解决 2 个任务。
  • 您是否有可能将"capturing groups"(“括号”)与"lookaraounds" 混淆? ...(?&lt;!a)、(?&lt;!b)、(?&lt;!c) 应该做什么/匹配?
  • “我有第二行来'调用'这些捕获的数字,如下所示:”我不明白这部分。 “呼唤”是什么意思?该代码有 $1、$2 等,表明它是一个替换字符串,但它也有lookbehind 和lookahead,它们在替换字符串中什么都不做。
  • 您是否尝试使用反向引用或替换?请提供minimal reproducible example。
  • 感谢 cmets!需要澄清的一些注意事项:@VGR 这是用于检查翻译的软件的代码:在第一行/字段中,我输入将在源(原始)文本中匹配的正则表达式模式,在第二行/字段中,我输入将匹配的正则表达式模式匹配目标(翻译)文本。我可以在其中一行中使用反向引用来“调出”另一行中捕获的内容。这就是为什么我在两行中都有环视,它们确保源文本中匹配的内容不分别被“a”、“b”或“c”包围,而目标文本中匹配的内容不被“n”包围。

标签: java regex regex-lookarounds regex-group


【解决方案1】:

您的正则表达式匹配空格,因为1,1 字符串的结果模式是(?&lt;!n)(1 1| | )(?!n),它可以匹配一个既不在空格前面也不在后面加空格的空格。

当替换反向引用与.replaceAll/.replaceFirst 中的任何字符串都不匹配时 它被分配一个空字符串(它被分配null 当使用 .find() / .matches()) 时,您仍然会在结果模式中获得空白替代项。

您可以利用此功能,并且通过在字符串替换模式中连接替换反向引用,每个替代项都有两个捕获组这一事实,完全摆脱了替代项:

搜索:(?&lt;!a)([0-9]),([0-9])(?!a)|(?&lt;!b)([0-9]) ([0-9])(?!b)|(?&lt;!c)([0-9])([0-9])(?!c)
替换:(?&lt;!n)($1 $2|$3 $4|$5 $6)(?!n)

注意反向引用是如何连接的:所有对奇数组的反向引用首先出现,然后对偶数组的所有反向引用被放置在一个不可替代的模式中。

请参阅regex demo。

请注意,即使备选方案的组数不同,您也可以为每个备选方案添加“假”空组,这种方法仍然有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-24
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    相关资源
    最近更新 更多