我有这个小班来对字符串进行多次替换:
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
public class MultipleReplace {
public static void main(String[] args) {
Map<String,String> tokens = new HashMap<String,String>();
tokens.put(":asd:", "<img src=asd.gif>");
tokens.put(":)", "<img src=sorriso.gif>");
String template = ":asd: bravo! :)";
String patternString = "(" + StringUtils.join(tokens.keySet(), "|") + ")";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(template);
StringBuffer sb = new StringBuffer();
while(matcher.find()) {
matcher.appendReplacement(sb, tokens.get(matcher.group(1)));
}
matcher.appendTail(sb);
System.out.println(sb.toString());
}
}
问题在于第二次替换,其中我有一个括号导致:
线程“main”中的异常java.util.regex.PatternSyntaxException:索引8附近的不匹配关闭')' (:)|:ASD:)
我如何逃避括号? 或者,你能建议一个替代方案来做多次替换吗?
非常感谢,对不起我的英语:)
修改
使用反斜杠转义')'也不起作用,它不会编译:
“无效的转义序列(有效转义序列为\ b \ t \ n \ f \ r \”\'\ \“”
新编辑
使用两个反斜杠编译,但不做替换。
最后编辑
最后找到解决方案,在构建模式时使用Pattern.quote。必须使用迭代器来完成循环。
这里有正确的代码:
package string;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MultipleReplace {
@SuppressWarnings("rawtypes")
public static void main(String[] args) {
Map<String,String> tokens = new HashMap<String,String>();
tokens.put(":asd:", "<img src=asd.gif>");
tokens.put(":)", "<img src=sorriso.gif>");
String template = ":asd: bravo! :)";
Iterator it = tokens.entrySet().iterator();
String patternString = "(";
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
patternString = patternString +Pattern.quote((String) pairs.getKey());
if (it.hasNext())
{
patternString = patternString + "|";
}
}
patternString = patternString + ")";
System.out.println(patternString);
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(template);
StringBuffer sb = new StringBuffer();
while(matcher.find()) {
matcher.appendReplacement(sb, tokens.get(matcher.group(1)));
}
matcher.appendTail(sb);
System.out.println(sb.toString());
}
}
如果我可以改进工作,请评论它!非常感谢你!
答案 0 :(得分:16)
像我在评论中写的那样使用Pattern.quote
。它适用于每个字符串,对于包含大量非字母数字字符的长字符串,它不易出错。
这是一个闪亮的(未经测试的)Java 8解决方案:
final Map<String, String> tokens = new HashMap<>();
tokens.put(":asd:", "<img src=asd.gif>");
tokens.put(":)", "<img src=sorriso.gif>");
final String template = ":asd: bravo! :)";
final String patternString = tokens.keySet()
.stream().map(Pattern::quote).collect(Collectors.joining("|"));
final Pattern pattern = Pattern.compile(patternString);
final Matcher matcher = pattern.matcher(template);
final StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, tokens.get(matcher.group(0)));
}
matcher.appendTail(sb);
System.out.println(sb.toString());
答案 1 :(得分:8)
使用反斜杠:\)
。必须转义Parens,因为它们可用于对正则表达式的部分进行分组。
String template = ":asd: bravo\\! :\\)";
答案 2 :(得分:0)
我会给出比Tim N更好的例子。
假设你有一个字符串字。
word = "http://www.randomwebsite.com/images/That Image (English)";
如果要用空格替换括号,只需执行:
word.replaceAll("\\(", " ");
你必须做2个双反斜杠才能让编译器闭嘴而不是抱怨。
还要记住,该函数返回一个String。所以你要做
word = word.replaceAll("\\(", " ");
除非您想看到它,否则请将其打印出来。