我试图替换匹配我的正则表达式的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
。为什么呢?
答案 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
解决了这个问题。这是正则表达式安全的。