у меня есть этот маленький класс для многократной замены строки:
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());
}
}
Пожалуйста, прокомментируйте это, если я могу улучшить работу! Большое спасибо!
tokens.put(Pattern.quote(original), replacement)
. Кстати, вам не нужна группа, используйтеmatcher.group(0)
. - person maaartinus   schedule 16.02.2011Pattern.quote
, вам не нужно и не следует избегать скобок. Так что это еще одно решение. - person maaartinus   schedule 16.02.2011