String的replaceAll()方法和转义字符

27

这条线

System.out.println("\\");

打印一个反斜杠符号 (\)。

System.out.println("\\\\");

打印双反斜杠 (\\)。明白了!

但在下面的代码中为什么要这样写:

class ReplaceTest
{
    public static void main(String[] args)
    {
        String s = "hello.world";
        s = s.replaceAll("\\.", "\\\\");
        System.out.println(s);
    }
}

输出是否为:

hello\world

取代

hello\\world

毕竟,replaceAll()方法是将一个点(\\.)替换为(\\\\)。

有人可以解释一下吗?

7个回答

27

使用正则表达式替换字符时,您可以使用后向引用,例如\1,以使用匹配中的分组进行替换。

然而,这意味着反斜杠是一个特殊字符,因此如果您确实想要使用反斜杠,则需要对其进行转义。

这意味着在Java字符串中使用它时需要转义两次。(首先是为了字符串解析器,然后是为了正则表达式解析器。)


3
基本上您的意思是字符串解析器将首先将 "\\" 解析为 "\",然后正则表达式解析器将进一步将其解析为 ""。是这样吗? - Surender Thakran
是的,我有点困惑,因为在问题的示例中,为什么字符串解析器不会将 \\. 解析为 \.,然后正则表达式会将其解析为 . - ametren
2
@ametren 没错。在替换的第一部分中,它确实是 \。因为他转义了点,因为那也有特殊的含义,所以它变成了 '.',然后被第二个参数中的字符串替换。 - Reverend Gonzo
没事,我刚才意识到我完全误读了问题。 - ametren

20

replaceAll方法的Javadoc中提到:

注意,在替换字符串中使用反斜杠 (\) 和美元符号 ($) 可能导致结果与将其视为字面替换字符串时不同。如需消除这些字符的特殊含义,请参阅Matcher.replaceAll并使用Matcher.quoteReplacement(java.lang.String)


3
感谢提到Matcher.quoteReplacement!+1。 编辑:删除代码(我无法使用迷你标记将其排版)。 - Christophe Blin
1
Pattern.quoteMatcher.quoteReplacement之间有一个非常重要的区别。如果您希望在搜索字符串中忽略元字符,您需要使用前者(Pattern.quote)。如果您想要在替换字符串中忽略它们(其语法略有不同),则需要使用后者(Matcher.quoteReplacement)。它们彼此不兼容,所以请使用正确的方法! - Christopher Schultz

8
如果您只需要替换确切的字符串而不是使用正则表达式进行替换,请在替换之前转义正则表达式控制字符。
String trickyString = "$Ha!I'm tricky|.|";
String safeToUseInReplaceAllString = Pattern.quote(trickyString);

6

这是我的评论的格式补充说明

s = s.replaceAll("\\.", Matcher.quoteReplacement("\\"));  

比起更加易读易懂且有意义
s = s.replaceAll("\\.", "\\\\\\");

0

我不喜欢这个正则表达式的实现方式。我们应该能够用一个反斜杠 '\' 转义字符,而不是 '\\'。但无论如何,如果你想要得到 THIS.Out_Of_That,你可以这样做:

String prefix = role.replaceFirst("(\\.).*", "");

所以你得到的前缀是 THIS;


0
反斜杠是Java字符串中的转义字符,例如,在Java中反斜杠具有预定义的含义。您必须使用“\”来定义单个反斜杠。如果您想要定义“\w”,则必须在正则表达式中使用“\\w”。如果要将反斜杠用作字面量,则必须键入\\\\,因为在正则表达式中,“\”也是一个转义字符。

0
我相信在这种情况下,使用replace而不是replaceAll会更容易。 当Reverend Gonzo谈到转义字符时,他给出了正确的答案。
使用replaceAll:
s = s.replaceAll("\\.", "\\\\\\\\");

使用replace函数:

s = s.replaceAll(".", "\\");

replace 只需要一个要匹配的字符串,而不是正则表达式。


1
你提到了replace(),但你两次使用了replaceAll(),你需要编辑你的答案吗? - gouessej

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