【问题标题】:Regex capturing group doesn't recognise group(1) despite matches() true正则表达式捕获组无法识别组(1),尽管匹配()为真
【发布时间】:2014-04-25 23:44:12
【问题描述】:

我正在用 Java 编写一些简单的(我认为是)正则表达式来删除直接出现在某些指定标点符号旁边的星号或 & 号。
这是我的原始代码:

String ptr = "\\s*[\\*&]+\\s*";
String punct1 = "[,;=\\{}\\[\\]\\)]"; //need two because bracket rules different for ptr to left or right
String punct2 = "[,;=\\{}\\[\\]\\(]";

out = out.replaceAll(ptr+"("+punct1+")|("+punct2+")"+ptr,"$1");

这不仅删除了字符串的“ptr”部分,还删除了punct! (即用空字符串替换匹配的字符串)
我通过以下方式进一步检查:

String ptrStr = ".*"+ptr+"("+punct1+")"+".*|.*("+punct2+")"+ptr+".*";
Matcher m_ptrStr = Pattern.compile(ptrStr).matcher(out);

发现:

m_ptrStr.matches() //returns true, but...
m_ptrStr.group(1) //returns null??

我不知道我做错了什么,因为我之前使用过这种精确的方法,并且使用了更复杂的正则表达式,并且 group(1) 总是返回捕获的组。一定有什么我没能发现的,所以..有什么想法吗?

【问题讨论】:

  • 无需引用{* 或字符类中的括号
  • 无论如何-我怀疑 .group(1) 在这里为空,因为它是您的第二组匹配
  • 哦!我认为 group(1) 是第一个匹配的组,无论它在正则表达式字符串的哪个位置。这解释了很多,谢谢!

标签: java regex capturing-group


【解决方案1】:

问题是你在每一边都有一个捕获组:

(regex1)|(regex2)

匹配器将使用第一个替代开始并搜索匹配;如果没有找到,它会尝试第二次替换。

但是,这些仍然是两组,并且只有一组会匹配。不匹配的将返回null,这就是你在这里发生的事情。

因此,您需要测试这两个组;既然你有匹配,至少有一个不会为空。

【讨论】:

  • 是的,对不起...我习惯于正则表达式语言,这不是一个值得关注的原因:/
【解决方案2】:

当您的模式中有| 时,这意味着匹配器可以匹配两种模式之一。无论它匹配哪个,它匹配的模式的任何捕获组都将返回子字符串——但是 other 模式的任何捕获组都将返回null,因为另一个模式并没有真正匹配。

看起来你的模式是

.*\s*[\*&]+\s*([,;=\{}\[\]\)]).*|.*([,;=\{}\[\]\(])+\s*[\*&]+\s*.*
------------- left ------------- -------------- right ------------

如果matches() 返回真,那么你的字符串匹配“左”模式,在这种情况下group(1) 将是非空的,group(2) 将是空的;否则它匹配“正确”模式,在这种情况下,group(1) 将为空,group(2) 非空。 [注意:匹配器不会尝试找出双方是否成功匹配。也就是说,如果左侧匹配,则不会检查右侧。]

【讨论】:

  • "匹配器不会检查它是否匹配两边"
  • @fge 我不是指第一个替代方案失败的情况,但我试图澄清措辞。关于其他正则表达式引擎的有趣(和令人惊讶)的花絮——谢谢。
猜你喜欢
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多