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 = "\\$[\\{]([^}]*)[\\}]";