正则表达式替换括号()内的内容

7
我尝试了这段代码:

string.replaceAll("\\(.*?)","");

但是它返回null。我错过了什么?

请注意,常用的表达式 \(.*?\) 在括号嵌套时会失败。请使用更精确的表达式 [^()]*,而不是懒惰的点星号。请参考我的答案以获得更好的解决方案。 - ridgerunner
4个回答

20

尝试:

string.replaceAll("\\(.*?\\)","");

你没有转义第二个括号,也没有在第一个括号前添加额外的“\”。


1
如果没有嵌套的括号,它可以正常工作。否则会失败。 - ridgerunner

11

首先,您是否希望删除括号及其内容?尽管问题的标题表示否定,但我假设您确实希望删除括号。

其次,括号之间的内容可以包含嵌套匹配的括号吗?此解决方案假定是。由于Java正则表达式不支持递归表达式,因此解决方案是首先创建一个匹配“最内层”括号的正则表达式,然后以迭代方式应用该正则表达式,从里到外替换它们。这是一个经过测试的Java程序,可以正确地删除(可能嵌套的)括号及其内容:

import java.util.regex.*;
public class TEST {
    public static void main(String[] args) {
        String s = "stuff1 (foo1(bar1)foo2) stuff2 (bar2) stuff3";
        String re = "\\([^()]*\\)";
        Pattern p = Pattern.compile(re);
        Matcher m = p.matcher(s);
        while (m.find()) {
            s = m.replaceAll("");
            m = p.matcher(s);
        }
        System.out.println(s);
    }
}

测试输入:

"stuff1 (foo1(bar1)foo2) stuff2 (bar2) stuff3"

测试输出:

"stuff1  stuff2  stuff3"

请注意,懒惰的“点星”解决方案永远不会起作用,因为它在嵌套时无法匹配最内层的括号集。 (即,在上面的示例中,它错误地匹配了:(foo1(bar1)。)这是一个非常常见的正则表达式错误:当存在更精确的表达式时,永远不要使用点! 在这种情况下,“最内层”匹配括号之间的内容包括任何不是开放或关闭括号的字符,(即使用: [^()]* 而不是: .*?)。

这是一个绝对精彩的答案。Java的正则表达式引擎再次咬了我一口,因为它缺乏对递归表达式的支持:/ - philomatic
@ridgerunner 如果我有这样的东西:"stuff1 [foo1[bar1]foo2] stuff2 [bar2] stuff3",该怎么办? - FaNaJ
@user3767784 - 你有什么问题吗?你的字符串中没有括号。如果你想匹配[方括号]而不是匹配括号,那么只需修改正则表达式,并将每个字面上的括号替换为字面上的方括号即可。例如:String re ="\\[[^\\[\\]]*\\]"; - ridgerunner
自从3.8版本以来,Apache Commons Lang现在附带了RegexUtils,其中包括用于递归匹配的实用程序。 - mancini0

2
尝试使用 string.replaceAll("\\(.*?\\)","")

上面的匹配“.*?”是非贪婪的,它将匹配到第一个右括号的出现。对于贪婪模式,只需使用“.*”。 - earcam
@earcam:是的,谢谢,我已经发现并将其编辑删除了。 - NPE

1

string.replaceAll("\\([^\\)]*\\)",""); 这样你就是说匹配一个括号,然后所有非闭合括号字符,最后是一个闭合括号。相比勉强或贪婪的.*匹配器,这通常更快。


在字符类中,您不需要转义括号。 - Tim Pietzcker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接