java escape скобка - PullRequest
       22

java escape скобка

14 голосов
/ 16 февраля 2011

У меня есть этот маленький класс для многократной замены строки:

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:)

Как мне избежать скобок? Или, вы можете предложить альтернативу, чтобы сделать эту множественную замену?

Большое спасибо и извините за мой английский:)

EDIT:

Выход с обратной косой чертой ')' тоже не работает, не скомпилируется:

"Недопустимая escape-последовательность (допустимыми являются \ b \ t \ n \ f \ r \" \ '\) "

NEW EDIT

с использованием двух обратных косых черт компилируется, но не выполняет замену.

ПОСЛЕДНИЕ РЕДАКТИРОВАТЬ

Наконец-то нашли решение, используя 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());
    }
}

Пожалуйста, прокомментируйте это, если я могу улучшить работу! Большое спасибо!

Ответы [ 3 ]

16 голосов
/ 16 февраля 2011

Используйте 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());
8 голосов
/ 16 февраля 2011

Используйте обратную косую черту: \). Парены должны быть экранированы, потому что их можно использовать для группировки частей регулярного выражения.

    String template = ":asd: bravo\\! :\\)";
0 голосов
/ 16 декабря 2012

Я приведу лучший пример, чем Тим Н.

Допустим, у вас есть строковое слово.

word = "http://www.randomwebsite.com/images/That Image (English)";

Если вы хотите заменить скобки пробелами, просто выполните:

word.replaceAll("\\(", " ");

Вы должны сделать две двойные косые черты, чтобы компилятор заткнулся, а не скулил.

Также имейте в виду, что функция возвращает строку. Так что вы бы сделали

word = word.replaceAll("\\(", " ");

Если вы не хотите его видеть, просто распечатайте его.

...