String replaceAll("¾") in java

19

我在我的Java代码中遇到了一个非常奇怪的错误,无法找出问题所在。

假设我有以下代码:

private void test()
{
    String test1 = replace("1.25");
    String test2 = replace("1.5");
    String test3 = replace("1.75");
}

private String replace(String s)
{
     s = s.replaceAll(".25", "¼");
     s = s.replaceAll(".5", "½");
     s = s.replaceAll(".75", "¾");
     return s;
}

那么结果将会是:

test1 = "¼"

test2 = "½"

test3 = "½" ??????????

有人能解释一下为什么test3变成了“½”吗?


在执行第三个replaceAll之前,使用alert(s)进行提示。查看传入的值是什么。 - prograhammer
s = s.replaceAll(Pattern.quote(".25"), "¼"); - Maroun
7个回答

27

您正在使用replaceAll()方法,该方法需要一个正则表达式。在正则表达式中,.表示“任何字符”。请改用replace()方法,它可以处理字面字符串。


7
或者使用Pattern#quote。 (说明:此句为编程语言 Java 中正则表达式相关方法的使用建议,建议使用Pattern#quote方法来转义正则表达式中的特殊字符,以确保其被视为普通字符而不是正则表达式的一部分) - Maroun
@JohanNordli 没问题,很高兴能帮助到您。 - arshajii

8

因为replaceAll使用了正则表达式。这意味着.被解释为通配符,也匹配7,所以.5匹配75。你可以使用\在正则表达式中进行转义,但请注意这也是一个字符串,这意味着你需要转义两次:所以replaceAll("\\.5", "½")将会实现你想要的效果。


1
是的,但实际上它并不是错误的,也不是离题的情况下,最起码可以选择不投赞成票或反对票,但是反对票绝对不合适,并且两个答案之间的时间少于一分钟,这使得反对票更加不恰当。 - Kiwy

5
问题在于正则表达式中的.表示任何字符。 replaceAll方法需要一个正则表达式作为参数,因此您应该使用其他方法,例如replace来替换字符串。

当我写我的答案时,我没有看到他的回答。 - Adam Arold
5
我认为你需要服用一颗快乐药丸 :) - Adam Arold
1
几颗开心药片后,经过反思,你是正确的。我已经撤回了我的踩票。 - Bathsheba
@Bathsheba 很高兴听到这个好消息 :) - Adam Arold

3

替换全部函数将第一个参数解释为正则表达式。".5"作为正则表达式将匹配任何后面跟着5的内容,例如你的字符串test2。请使用反斜杠转义'.'字符:

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

应该是双反斜杠! - Gyro Gearless
你确定吗?反斜杠并不是字面意义上的符号,而是为了转义.字符(必须承认我在Java中没有尝试过这个,但其他正则表达式实现允许这样做)。 - Slicedpan
没错,你说得对,因为这是一个字符串,正如@MartinRing所解释的那样。 - Slicedpan

3

replaceAll使用正则表达式作为第一个参数,需要找到并替换的内容。在正则表达式中,点号.是元字符,它将匹配除换行符以外的所有字符。因此,当您使用该方法时,请注意:

s = s.replaceAll(".5", "½");

"1.75" 变为 "1.5" 时,.5 可以与 75 匹配(因为 . 匹配所有字符)。因此,在进行这样的更改后:

1.75 
  -- will become 
1.½ 

请注意,1.25 之所以能正常工作,是因为你在 .5 之前使用了 .25

为了防止这种行为,您需要转义句点。您可以通过以下方式实现:

  • 在句点前加上 \(请记住,要创建 \ 字面量,您需要将其写成 "\\"):"\\."
  • 将句点放在字符类中 [.]
  • \Q\E 包围它,分别表示引号的开头和结尾:\\Q.\\E
  • 也可以使用 Pattern.quote(".") 来用 \Q\E 包围它,
  • 在 Pattern 实例编译时,您可以添加 Pattern.LITERAL 标志,以使所有在模式字面量中使用的元字符都生效。

如果您想让整个模式都成为简单字面量,可以使用 replace 而不是 replaceAll,它会自动使用 Pattern.LITERAL 标志,并将所有正则表达式元字符更改为简单字面量。

因此,您可以尝试类似以下的内容:

return s.replaceAll("\\.25", "¼").replaceAll("\\.5", "½").replaceAll("\\.75", "¾");

或更简单
return s.replace(".25", "¼").replace(".5", "½").replace(".75", "¾");

这个解释得非常好,感谢您花时间写了一个非常好的答案。 - Johan Nordli

1

使用String.replace()替代String.replaceAll()

像这样做

    private String replace(String s)
    {
        s = s.replace(".25", "¼");
        s = s.replace(".5", "½");
        s = s.replace(".75", "¾");
        return s;
    }

1
replaceAll()的第一个参数是REGEX,'.'表示REGEX区域内的任何字符。

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