IllegalArgumentException:replaceFirst时非法组引用

时间:2015-06-07 10:59:34

标签: java regex

我试图替换匹配我的正则表达式的String的第一次出现,同时迭代这样的出现:

(此代码非常简化,所以不要试图找到更大的意义)

Matcher tagsMatcher = Pattern.compile("\\{[sdf]\\}").matcher(value);

int i = 0;
while (tagsMatcher.find()) {
    value = value.replaceFirst("\\{[sdf]\\}", "%" + i + "$s");
    i++;
}

我在执行IllegalArgumentException: Illegal group reference时获得replaceFirst。为什么呢?

4 个答案:

答案 0 :(得分:2)

replacement中{p> replaceFirst(regex,replacement)部分可以包含对regex匹配的群组的引用。为此,它正在使用

  • $x语法,其中x是表示组号的整数,
  • ${name}其中name是指定群组的名称(?<name>...)

由于此功能$被视为replacement中的特殊字符,因此如果您想要$字面值,则需要

  • 使用\
  • 之类的replaceFirst(regex,"\\$whatever")转义它
  • Matcher使用Matcher.quote方法replaceFirst(regex,Matcher.quote("$whatever"))
  • value = value.replaceFirst("\\{[sdf]\\}", "%" + i + "\\$s"); 为您转义

但你不应该使用

matcher.appendReplacement(StringBuffer, replacement)

内部循环,因为每次执行时,都需要遍历整个字符串以查找要替换的部分,因此每次需要从头开始时效率非常低。

正则表达式引擎以matcher.appendTail(StringBuffer)appendReplacement的形式解决了这种低效问题。

  • appendTail方法向StringBuffer添加所有数据,直到当前匹配为止,并允许您指定应该由正则表达式部分匹配的内容
  • StringBuffer sb = new StringBuffer(); int i = 0; Matcher tagsMatcher = Pattern.compile("\\{[sdf]\\}").matcher(value); while (tagsMatcher.find()) { tagsMatcher.appendReplacement(sb, Matcher.quoteReplacement("%" + (i++) + "$s")); } value = sb.toString(); 添加在最后匹配的部分之后存在的部分

所以你的代码应该更像

reduce

答案 1 :(得分:2)

特殊字符$可以处理简单方法。请查看以下示例

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 

答案 2 :(得分:0)

你需要逃避美元符号。

value = value.replaceFirst("\\{[sdf]\\}", "%" + i + "\\$s");

发生非法组引用错误主要是因为尝试引用一个实际上不存在的组。

答案 3 :(得分:0)

我通过使用Apache Commons org.apache.commons.lang3.StringUtils.replaceOnce解决了这个问题。这是正则表达式安全的。