1

我正在用 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) 总是返回捕获的组。一定有什么我没能发现的,所以..有什么想法吗?

4

2 回答 2

2

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

(regex1)|(regex2)

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

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

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

于 2014-03-19T15:44:06.450 回答
1

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

看起来你的模式是

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

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

于 2014-03-19T15:42:26.247 回答