Java中使用String.replaceAll进行正则表达式替换

10
我想要替换一个Java字符串的值,以下代码无法实现此功能。
        cleanInst.replaceAll("[<i>]", "");
        cleanInst.replaceAll("[</i>]", "");
        cleanInst.replaceAll("[//]", "/");
        cleanInst.replaceAll("[\bPhysics Dept.\b]", "Physics Department");
        cleanInst.replaceAll("[\b/n\b]", ";");
        cleanInst.replaceAll("[\bDEPT\b]", "The Department");
        cleanInst.replaceAll("[\bDEPT.\b]", "The Department");
        cleanInst.replaceAll("[\bThe Dept.\b]", "The Department");
        cleanInst.replaceAll("[\bthe dept.\b]", "The Department");
        cleanInst.replaceAll("[\bThe Dept\b]", "The Department");
        cleanInst.replaceAll("[\bthe dept\b]", "The Department");
        cleanInst.replaceAll("[\bDept.\b]", "The Department");
        cleanInst.replaceAll("[\bdept.\b]", "The Department");
        cleanInst.replaceAll("[\bdept\b]", "The Department");

什么是实现上述替换的最简单方法?

1
你说的“不工作”是什么意思? - stinepike
1
删除方括号([])。这些是字符类。如果还有其他问题,请提供更具体的信息。 - Reinstate Monica -- notmaynard
你是否了解正则表达式中的字符类是什么?http://regex.info - fge
5
字符串是不可变的。 - SLaks
2
忽略大小写修饰符可以用于许多dept替换。 - Isaac
2
正如@SLaks所指出的那样:字符串是不可变的。如果您不在某个地方存储String.replaceAll()的返回值,那么您的代码将无法执行任何操作。目前,您的代码没有对返回值进行任何处理。 - jahroy
3个回答

14

如果你在使用连续的函数,那么会有问题。每次调用都会重新编译正则表达式。最好将它们创建为常量。你可以像这样做。

private static final Pattern[] patterns = {
    Pattern.compile("</?i>"),
    Pattern.compile("//"),
    // Others
};

private static final String[] replacements = {
    "",
    "/",
    // Others
};

public static String cleanString(String str) {
    for (int i = 0; i < patterns.length; i++) {
        str = patterns[i].matcher(str).replaceAll(replacements[i]);
    }
    return str;
}

现在我们每次创建Matcher对象,而不是使用Pattern。这样做有什么好处呢? - rpattabi
因为编译正则表达式模式的成本比为(预编译的)模式创建匹配器更高? - Ade Miller

9
cleanInst.replaceAll("[<i>]", "");

should be:

cleanInst = cleanInst.replaceAll("[<i>]", "");

由于String类是不可变的,并且不改变其内部状态,即replaceAll()返回一个与cleanInst不同的新实例。


3

您应该阅读一份基础的正则表达式教程

在那之前,您可以像这样完成您想要做的事情:

cleanInst = cleanInst.replace("//", "/");
cleanInst = cleanInst.replaceAll("</?i>", "");
cleanInst = cleanInst.replaceAll("/n\\b", ";")
cleanInst = cleanInst.replaceAll("\\bPhysics Dept\\.", "Physics Department");
cleanInst = cleanInst.replaceAll("(?i)\\b(?:the )?dept\\b\\.?", "The Department");

你可能可以将所有这些替换操作串联起来(但我不知道正确的Java语法)。
关于单词边界:通常\b只在字母数字字符直接前后才有意义。
例如,\b/n\b仅会匹配在字母数字字符之前且在非字母数字字符之后的/n,因此它会匹配"a/n!"但不会匹配"foo /n bar"

1
你的答案很不错,但为什么对于“the”使用非捕获组?这只是为了“性能”吗?因为在我看来,可读性下降比性能提高更多。顺便说一句,我怀疑/n应该是\n - Bohemian
1
我只是习惯这样做。除非我想捕获一个组,否则我从不使用捕获括号。我同意清楚地表达自己的意图和可读性之间存在紧张关系。 - Tim Pietzcker

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