Matcher.appendReplacement с буквальным текстом
Я использую Matcher.appendReplacement(), и он отлично работал, пока в моей заменяющей строке не было $2:
Обратите внимание, что обратная косая черта (\) и доллар знаки ($) в заменяющей строке может привести к тому, что результаты будут разными чем если бы он рассматривался как буквальная строка замены. доллар знаки могут рассматриваться как ссылки на захваченные подпоследовательности, как описано выше, а обратная косая черта используется для исключить буквенные символы в строка замены.
Есть ли способ удобства где-нибудь, который избежит всех обратных косых черт\и знаков доллара $с обратным слэшем? Или я должен написать сам? Похоже, это не так сложно, просто было бы неплохо, если бы они дали вам один > : (
изменить:, так как они дают вам один, мне нужно replace(">:(", ":-)");
Ответы
Ответ 1
Используйте Matcher.quoteReplacement на заменяющей строке.
К сожалению, "простота использования" в этом случае конфликтует с сильной типизацией. [Объяснение: Объектом статического типа Java java.lang.String
является любая неизменяемая последовательность char
s. Он не сообщает вам формат этих необработанных данных. В этом случае у нас есть текст, который, вероятно, имеет смысл для пользователя, текст, закодированный в мини-языке для замены, и текст, закодированный в мини-языке для шаблона. Система типов Java не имеет возможности отличить их (хотя вы можете делать забавные вещи с помощью меток проверки типов на основе аннотаций, часто избегая уязвимостей XSS или SQL/командной инъекции). Для мини-языка шаблонов вы можете преобразовать форму с помощью Pattern.compile
, хотя это специфическое использование, и большинство методов API игнорируют его (для удобства использования). Можно было бы записать эквивалент ReplacementText.compile
. Кроме того, вы можете игнорировать мини-языки и искать библиотеки как "DSL". Но все это не помогает случайной простоте использования.]
Ответ 2
Вот еще один вариант:
matcher.appendReplacement(stringbuffer, "");
stringbuffer.append(replacement);
appendReplacement()
обрабатывает задание копирования по тексту между совпадениями, затем StringBuffer#append()
добавляет ваш заменяющий текст без фальсификаций. Это особенно удобно, если вы генерируете заменяющий текст динамически, как в
Ответ 3
Я получил его для работы со следующим, но мне больше нравится решение Tom Hawtin: -)
private static Pattern escapePattern = Pattern.compile("\\$|\\\\");
replacement = escapePattern.matcher(replacement).replaceAll("\\\\$0");
matcher.appendReplacement(stringbuffer, replacement);
Решение Tom:
matcher.appendReplacement(stringbuffer, Matcher.quoteReplacement(replacement));