为什么replaceAll会因“非法组参考”而失败?

时间:2012-08-11 10:00:57

标签: java regex

我需要更换

\\\s+\\$\\$ to $$

我用过

String s = "  $$";
s = s.replaceAll("\\s+\\$\\$","$$");

但它会引发异常

  

java.lang.IllegalArgumentException:非法组引用

8 个答案:

答案 0 :(得分:78)

来自String#replaceAll javadoc

  

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

因此可以使用Matcher#quoteReplacement来完成对任意替换字符串的转义:

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

也可以使用Pattern#quote

完成模式的转义
String s = "  $$";
s = s.replaceAll("\\s+" + Pattern.quote("$$"), Matcher.quoteReplacement("$$"));

答案 1 :(得分:46)

在第二个参数中使用"\\$\\$"

String s="  $$";
s=s.replaceAll("\\s+\\$\\$","\\$\\$");
//or
//s=s.replaceAll("\\s+\\Q$$\\E","\\$\\$");

$是正则表达式替换参数中的组符号

所以你需要逃避它

答案 2 :(得分:5)

这里的问题不是正则表达式,而是替换:

$用于指代()个匹配组。因此你需要使用反斜杠(以及第二个反斜杠以使java编译器满意)来转义它:

String s="  $$";
s = s.replaceAll("\\s+\\$\\$", "\\$\\$");

答案 3 :(得分:2)

这是正确的方法。用escaped \\ $替换literar $ str.replaceAll("\\$", "\\\\\\$")

答案 4 :(得分:1)

public class ScreenDetailsRepoService {

  @Autowired
  private MongoTemplate mongoTemplate;

  private String[] screenFields;

  @PostConstruct
  public void init() {
    screenFields = ClassUtil.getFieldName(DetailsEntity.class);
  }

  public ScreenDetailsEntity getScreenDetails(final @NonNull String page,
      final @NonNull String client, final String module,
      final String locale, final Integer hotelId, final Integer countryId
  ) throws NoDataFoundException {
    ScreenDetailsEntity screenDetailsEntity;
    Aggregation aggregation = newAggregation(
        match(where(PAGE).is(page)),
        project(screenFields),
        limit(1)
    );
    long t1 = System.currentTimeMillis();
    screenDetailsEntity = mongoTemplate.aggregate(aggregation, COLLECTION_NAME, ScreenDetailsEntity.class).getUniqueMappedResult();
    log.info(
        "DB Query: ScreenDetailsRepoService : getScreenDetails - Time taken for db requests : {} milliseconds",
        (System.currentTimeMillis() - t1));
    if (screenDetailsEntity == null) {
      log.error(
          "ScreenDetailsRepoService::getScreenDetails - No data found for for page {} ,module {}, locale {}, hotel {}, country {}",
          page, module, locale, hotelId, countryId);
      throw new NoDataFoundException("No data found");
    }
    return screenDetailsEntity;
  }

}

答案 5 :(得分:0)

$在替换字符串和正则表达式中具有特殊含义,因此您也必须在那里将其转义:

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

答案 6 :(得分:0)

String s="$$";
        s=s.replaceAll("\\s+\\$\\$","$$");

答案 7 :(得分:0)

我遇到了同样的问题,所以我最终用split来实现全部替换 它解决了我的例外

public static String replaceAll(String source, String key, String value){
    String[] split = source.split(Pattern.quote(key));
    StringBuilder builder = new StringBuilder();
    builder.append(split[0]);
    for (int i = 1; i < split.length; i++) {
        builder.append(value);
        builder.append(split[i]);
    }
    while (source.endsWith(key)) {
        builder.append(value);
        source = source.substring(0, source.length() - key.length());
    }
    return builder.toString();
}