Java PatternSyntaxException:字符串替换非法重复?

我正在尝试编写一个接受String的方法,检查它是否有某些令牌的实例(例如${fizz}${buzz}${foo}等)并用一个新的字符串替换每个令牌。从Map

例如,如果我将此方法传递给以下字符串:

“现在如何$ {fizz} cow。$ {buzz}奇形怪状的$ {foo}。”

如果该方法参考了以下Map

 Key Value ========================== "fizz" "brown" "buzz" "arsonist" "foo" "feet" 

然后结果字符串将是:

“怎么现在是棕色的牛。纵火犯的脚形状奇特。”

这是我的方法:

 String substituteAllTokens(Map tokensMap, String toInspect) { String regex = "\\$\\{([^}]*)\\}"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(toInspect); while(matcher.find()) { String token = matcher.group(); // Ex: ${fizz} String tokenKey = matcher.group(1); // Ex: fizz String replacementValue = null; if(tokensMap.containsKey(tokenKey)) replacementValue = tokensMap.get(tokenKey); else throw new RuntimeException("String contained an unsupported token."); toInspect = toInspect.replaceFirst(token, replacementValue); } return toInspect; } 

当我运行它时,我得到以下exception:

 Exception in thread "main" java.util.regex.PatternSyntaxException: Illegal repetition near index 0 ${fizz} ^ at java.util.regex.Pattern.error(Pattern.java:1730) at java.util.regex.Pattern.closure(Pattern.java:2792) at java.util.regex.Pattern.sequence(Pattern.java:1906) at java.util.regex.Pattern.expr(Pattern.java:1769) at java.util.regex.Pattern.compile(Pattern.java:1477) at java.util.regex.Pattern.(Pattern.java:1150) at java.util.regex.Pattern.compile(Pattern.java:840) at java.lang.String.replaceFirst(String.java:2158) ...rest of stack trace omitted for brevity (but available upon request!) 

我为什么要这个? 什么是正确的解决方案? 提前致谢!

${fizz}

{是正则表达式引擎的一个指示器,您即将开始重复指示,如{2,4} ,这意味着’前一个令牌的2到4倍’。 但是{f是非法的,因为它必须跟一个数字,所以它会引发exception。

您需要转义所有正则表达式元字符(在本例中${} )(尝试使用http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#quote( java.lang.String) )或使用一个不同的方法,用字符串替换字符串,而不是字符串的正则表达式。

正如Patashu所指出的,问题在于replaceFirst(token, replacementValue) ,它需要第一个参数中的正则表达式,而不是文字。 将它更改为replaceFirst(Pattern.quote(token), replacementValue) ,你就可以了。

我也改变了第一个正则表达式,因为它用+而不是*更快,但这不是必需的。

 static String substituteAllTokens(Map tokensMap, String toInspect) { String regex = "\\$\\{([^}]+)\\}"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(toInspect); String result = toInspect; while(matcher.find()) { String token = matcher.group(); // Ex: ${fizz} String tokenKey = matcher.group(1); // Ex: fizz String replacementValue = null; if(tokensMap.containsKey(tokenKey)) replacementValue = tokensMap.get(tokenKey); else throw new RuntimeException("String contained an unsupported token."); result = result.replaceFirst(Pattern.quote(token), replacementValue); } return result; } 

改编自Matcher.replaceAll

 boolean result = matcher.find(); if (result) { StringBuffer sb = new StringBuffer(); do { String tokenKey = matcher.group(1); // Ex: fizz String replacement = Matcher.quoteReplacement(tokensMap.get(tokenKey)); matcher.appendReplacement(sb, replacement); result = matcher.find(); } while (result); matcher.appendTail(sb); return sb.toString(); } 

使用String-replaceAll。 用于测试“SESSIONKEY1”的示例输入字符串:

“$ {} SOMESTRING.properties.SESSIONKEY1”

  String pattern = "\\\"\\$\\{SOMESTRING\\.[^\\}]+\\}\\\""; System.out.println(pattern); String result = inputString.replaceAll(pattern, "null"); return result.toString(); 

你可以让你的RegEx有点难看,但这会奏效

 String regex = "\\$[\\{]([^}]*)[\\}]";