Java 字符串 ReplaceAll 和 ReplaceFirst 在替换文本的 $ 符号处失败

Posted

技术标签:

【中文标题】Java 字符串 ReplaceAll 和 ReplaceFirst 在替换文本的 $ 符号处失败【英文标题】:Java String ReplaceAll and ReplaceFirst Fails at $ Symbol at Replacement Text 【发布时间】:2012-12-18 15:15:44 【问题描述】:

我写了这段代码:

public static void main(String args[]) throws Exception 
    String template = "The user has spent amount in a day";
    String pattern = "amount";
    String output = template.replaceAll(pattern, "$ 100");
    System.out.println(output);

这就是我运行它时发生的情况:

Exception in thread "main" java.lang.IllegalArgumentException: Illegal group reference
        at java.util.regex.Matcher.appendReplacement(Matcher.java:713)
        at java.util.regex.Matcher.replaceAll(Matcher.java:813)
        at java.lang.String.replaceAll(String.java:2190)
        at demo.BugDemo.main(BugDemo.java:16)
Java Result: 1

我正在从文件中读取数据。我应该转义文件数据中的所有$ 符号,还是这是一个不必要的过程?有没有其他类或库来处理这种情况?

在替换文本中(不是在正则表达式中)有一个特殊符号有什么问题?

注意事项:

我不想检查每个字符以进行转义。这就是我问这个问题的原因。

我使用的是 Java 6。

【问题讨论】:

试试\\\$; $ 我相信是一个特殊的字符。 @Telthien:不是 Java 语言。就正则表达式而言,它。这是你的意思吗? (您的评论不清楚。) 哦,是的,哎呀。将转义改为\\\$ @Telthien:为什么要使用三个反斜杠?它不需要从 Java 的角度转义。 @Telthien 该问题询问模式何时涉及特殊字符,与我的问题完全不同。我的文字中有特殊字符。 【参考方案1】:

String.replaceAll 以正则表达式 matching 模式作为其第一个参数,正则表达式 replacement 模式作为其第二个参数 - 而$ 具有特定含义在正则表达式中(在匹配模式和替换模式中,虽然在不同的意义上)。

只需改用String.replace,我怀疑您的所有问题都会消失。只有当您真正想要通过正则表达式匹配/替换时,您才应该使用replaceAll - 我认为您在这种情况下不会这样做。

编辑:至于你的问题:

在替换文本中(不是在正则表达式中)有一个特殊符号有什么问题?

replaceAll 的文档再次说明了这一点:

请注意,替换字符串中的反斜杠 (\) 和美元符号 ($) 可能会导致结果与将其视为文字替换字符串时的结果不同;见Matcher.replaceAll。如果需要,请使用 Matcher.quoteReplacement(java.lang.String) 隐藏这些字符的特殊含义。

因此,如果您想将 匹配 模式视为正则表达式,而不是替换,则使用 Matcher.quoteReplacement

【讨论】:

你检查过replaceFirst 的文档吗?是的,它仍然使用正则表达式和替换 patterns为什么你要使用replaceAllreplaceFirst 我想用“y”替换第一次出现的“x”,而不是其余的。那么有什么替代方案呢? @Jus12:听起来你应该问一个新问题,因为这不是这个问题的内容。一种选择是使用indexOf 查找x,然后使用substring 和连接。可能还有另一种选择 - 很可能有关于此案的问题,但不是 this 问题。 感谢您的回答。另请注意,相同的解释和解决方案适用于 appendReplacement 方法。 @ChristianGosch:引用文档:“请注意,替换字符串中的反斜杠 (\) 和美元符号 ($) 可能会导致结果与将其视为文字替换时不同字符串;参见 Matcher.replaceAll。”这对我来说似乎很清楚。 (它不会将其视为正则表达式;它的处理方式与处理正则表达式替换中的替换字符串的方式相同。)【参考方案2】:

在替换字符串中,$ 是一个特殊字符:它用于从要替换的模式中获取匹配的组。你可以阅读更多关于它的信息here。

要解决此问题,您可以引用替换字符串以从 $ 字符中删除所有特殊含义:

import java.util.regex.Matcher;
// ...
String output = template.replaceAll(pattern, Matcher.quoteReplacement("$ 100"));

【讨论】:

为什么要这样做而不是仅仅使用不使用正则表达式的 API? @JonSkeet 好点,如果不需要 replaceAll 你的答案会更好。 @kamaci 替换文本不是正则表达式,但它仍然很特别。 $ 字符在替换文本中是特殊的。阅读此链接了解更多信息:docs.oracle.com/javase/6/docs/api/java/lang/… @CoryKendall 我应该将 Matcher.quoteReplacement 用于 replaceFirst 还是有其他方法?【参考方案3】:

可以处理特殊字符$ 的方法很简单。 检查以下示例

public static void main(String args[])
        String test ="Other company in $ city ";
        String test2 ="This is test company ";
        try
            test2= test2.replaceFirst(java.util.regex.Pattern.quote("test"),  Matcher.quoteReplacement(test));
            System.out.println(test2);
            test2= test2.replaceAll(java.util.regex.Pattern.quote("test"),  Matcher.quoteReplacement(test));
            System.out.println(test2);
        catch(Exception e)
            e.printStackTrace();
        
    

输出:

This is Other company in $ city  company 
This is Other company in $ city  company 

【讨论】:

【参考方案4】:

试试这个

 String template = "The user has spent amount in a day";
 String pattern = "amount";
 String output = template.replaceAll(pattern, "\\$ 100");
 System.out.println(output);

【讨论】:

【参考方案5】:

$ 用于指定替换组的符号。你需要逃避它:

String output = template.replaceAll(pattern, "\\$ 100");

【讨论】:

以上是关于Java 字符串 ReplaceAll 和 ReplaceFirst 在替换文本的 $ 符号处失败的主要内容,如果未能解决你的问题,请参考以下文章

java去除字符串空格

JS 中 ReplaceAll 方法

浅谈java中replace和replaceAll的区别

浅谈java中replace和replaceAll的区别

浅谈java中replace和replaceAll的区别

java replace和replaceAll