尽管matches()为true,但正则表达式捕获组无法识别组(1)

时间:2014-03-19 15:34:50

标签: java regex capturing-group

我正在用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??

我不知道我做错了什么,因为我之前使用了这个精确的方法,因为更复杂的正则表达式和组(1)总是返回捕获的组。必须有一些我无法发现的东西,所以......任何想法?

2 个答案:

答案 0 :(得分:2)

问题是您在每一侧都有一个捕获组的替换:

(regex1)|(regex2)

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

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

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

答案 1 :(得分:1)

如果模式中有|,则表示匹配器可以匹配两种模式中的一种。无论匹配哪一个,它匹配的模式的任何捕获组都将返回子串 - 但其他模式的任何捕获组都将返回null,因为其他模式不是真的匹配。

看起来你的模式是

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

如果matches()返回true,则表示您的字符串与“左”模式匹配,在这种情况下group(1)将为非空,group(2)将为空;或者它匹配“正确”模式,在这种情况下group(1)将为空并且group(2)为非空。 [注意:匹配器不会试图找出两个方是否成功匹配。也就是说,如果左侧匹配,则不会检查右侧。]