



Поскольку Java 1.5, да:
Pattern.quote("");
Я просто хочу указать, что этот способ экранирования применяется также к выражениям, которые вы вводите после. Это может быть удивительно. Если вы сделаете "mouse".toUpperCase().replaceAll("OUS","ic"), он вернет MicE. Вы не ожидали, что он вернет MICE, потому что вы не применили toUpperCase() к ic. В моем примере quote() также применяется на вставке .* посредством replaceAll(). Вы должны сделать что-то еще, возможно, .replaceAll("*","\E.*\Q") подойдет, но это нелогично.
@Parameleon: Лучшее решение соответствующей проблемы - использовать метод split-map-mkString. ".wav" .split ("\\."). map (Pattern.quote) .mkString ("."). r
@Paramaeleon Приводит к ошибке для меня, так как первый аргумент в replaceAll является регулярным выражением.
@Paramaleon Если бы это сработало путем добавления отдельных экранирований, ваш первоначальный пример все равно не сделал бы то, что вы хотели ... если бы он экранировал символы по отдельности, он превратил бы *.wav в шаблон регулярного выражения \*\.wav, а replaceAll превратил бы его в \.*\.wav, это означает, что он будет соответствовать файлам, имя которых состоит из произвольного количества точек, за которыми следует .wav. Скорее всего, вам понадобился бы replaceAll("\*", ".*"), если бы они выбрали более хрупкую реализацию, которая полагается на распознавание всех возможных активных символов регулярных выражений и их экранирование по отдельности ... Было бы это намного проще?
Или, скорее, в сочетании с комментарием Адама Дженсена, вам пришлось бы использовать replaceAll("\\\*", ".*")
@Paramaeleon: вариант использования - "*.wav".replaceAll(Pattern.quote("*"), ".*").
На самом деле ни один из ответов мне не помог, но потом я подумал: я попытался сделать возможным простой ввод данных пользователем, где * просто означает, например, .*. Пользователь, конечно, ничего не знает о регулярных выражениях, поэтому теоретически он может использовать строки регулярных выражений, такие как .Hello*you?. Невозможно использовать Pattern.quote(string), а затем заменить * на .* и наоборот, потому что это будет цитировать всю строку. Просто split, строка для *, затем заключите в кавычки каждую часть результирующего массива и снова соедините все вместе с .* между ними. Надеюсь, это помогло тому, кто искал то же самое :)
Я думаю, что вам нужен \Q\E. Также см. Pattern.quote(s), представленный в Java5.
Подробнее см. В документации Шаблон javadoc.
Мне любопытно, есть ли разница между этим и использованием флага LITERAL, поскольку javadoc говорит, что нет встроенного флага для включения и выключения LITERAL: java.sun.com/j2se/1.5.0/docs/api/java/util/regex/…
Обратите внимание, что буквальное использование \ Q и \ E нормально, только если вы знаете свой ввод. Pattern.quote (s) также будет обрабатывать случай, когда ваш текст действительно содержит эти последовательности.
Разница между Pattern.quote и Matcher.quoteReplacement была мне непонятна, пока я не увидел следующий пример.
s.replaceFirst(Pattern.quote("text to replace"),
Matcher.quoteReplacement("replacement text"));
В частности, Pattern.quote заменяет специальные символы в строках поиска регулярных выражений, например. | + () И т. Д., А Matcher.quoteReplacement заменяет специальные символы в строках замены, например \ 1 для обратных ссылок.
Я не согласен. В Pattern.quote аргумент заключен в \ Q и \ E. Не экранирует специальные символы.
Matcher.quoteReplacement ("4 $ &% $") производит "4 \ $ &% \ $". Он экранирует специальные символы.
Другими словами: quoteReplacement заботится только о двух символах $ и \ , которые могут, например, использоваться в замещающих строках как обратные ссылки или . Поэтому его нельзя использовать для экранирования / кавычки регулярного выражения.
Потрясающие. Вот пример, в котором мы хотим заменить $Group$ на T$UYO$HI. Символ $ особенный как в шаблоне, так и в замене: "$Group$ Members".replaceFirst(Pattern.quote("$Group$"), Matcher.quoteReplacement("T$UYO$HI"))
Во-первых, если
в конце не будет 1. Он будет смотреть на регулярное выражение поиска для первой совпадающей группы и вложенной ТО в. Это то, что $ 1, $ 2 или $ 3 означают в тексте замены: совпадающие группы из шаблона поиска.
Я часто вставляю длинные строки текста в файлы .properties, а затем создаю из них темы и тела сообщений электронной почты. Действительно, похоже, что это способ по умолчанию для i18n в Spring Framework. Я помещаю теги XML в качестве заполнителей в строки и использую replaceAll () для замены тегов XML значениями во время выполнения.
Я столкнулся с проблемой, когда пользователь вводил цифру в долларах и центах со знаком доллара. replaceAll () подавился этим, и в stracktrace появилось следующее:
java.lang.IndexOutOfBoundsException: No group 3
at java.util.regex.Matcher.start(Matcher.java:374)
at java.util.regex.Matcher.appendReplacement(Matcher.java:748)
at java.util.regex.Matcher.replaceAll(Matcher.java:823)
at java.lang.String.replaceAll(String.java:2201)
В этом случае пользователь ввел где-то «$ 3» в свой ввод, а replaceAll () искал в регулярном выражении поиска третью совпадающую группу, не нашел ее и рванул.
Данный:
// "msg" is a string from a .properties file, containing "<userInput />" among other tags
// "userInput" is a String containing the user's input
замена
msg = msg.replaceAll("<userInput />", userInput);
с
msg = msg.replaceAll("<userInput />", Matcher.quoteReplacement(userInput));
решил проблему. Пользователь мог без проблем вводить любые символы, включая знаки доллара. Он вел себя именно так, как и следовало ожидать.
Чтобы получить защищенный шаблон, вы можете заменить все символы на «\\\\», кроме цифр и букв. И после этого вы можете вставить в этот защищенный шаблон свои специальные символы, чтобы этот шаблон работал не как глупый цитируемый текст, а действительно как шаблон, а был ваш собственный. Без специальных символов пользователя.
public class Test {
public static void main(String[] args) {
String str = "y z (111)";
String p1 = "x x (111)";
String p2 = ".* .* \(111\)";
p1 = escapeRE(p1);
p1 = p1.replace("x", ".*");
System.out.println( p1 + "-->" + str.matches(p1) );
//.*\ .*\ \(111\)-->true
System.out.println( p2 + "-->" + str.matches(p2) );
//.* .* \(111\)-->true
}
public static String escapeRE(String str) {
//Pattern escaper = Pattern.compile("([^a-zA-z0-9])");
//return escaper.matcher(str).replaceAll("\\");
return str.replaceAll("([^a-zA-Z0-9])", "\\");
}
}
Вам не нужно покидать пробелы. Таким образом, вы можете изменить свой шаблон на «([^ a-zA-z0-9])».
Маленькая опечатка, серьезные последствия: «([^ a-zA-z0-9])» также не соответствует (т.е. не экранируется) [, \,], ^ которого вы, безусловно, хотите избежать! Опечатка - это вторая буква «z», которая должна быть буквой «Z», в противном случае включается все от ASCII 65 до ASCII 122.
Может быть, уже слишком поздно отвечать, но вы также можете использовать Pattern.LITERAL, который игнорирует все специальные символы при форматировании:
Pattern.compile(textToFormat, Pattern.LITERAL);
Это особенно приятно, потому что его можно комбинировать с Pattern.CASE_INSENSITIVE.
Pattern.quote ("блабла") прекрасно работает.
Pattern.quote () прекрасно работает. Он включает предложение с символами «\ Q» и «\ E», и если оно действительно экранирует «\ Q» и «\ E». Однако, если вам нужно выполнить экранирование реального регулярного выражения (или пользовательское экранирование), вы можете использовать этот код:
String someText = "Some/s/wText*/,**";
System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));
Этот метод возвращает: Некоторые / \ s / wText * / \, **
Код для примера и тесты:
String someText = "Some\\E/s/wText*/,**";
System.out.println("Pattern.quote: "+ Pattern.quote(someText));
System.out.println("Full escape: "+someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));
+1 Это очень хорошо работает для преобразования указанной пользователем строки нестандартных символов в шаблон, совместимый с регулярными выражениями. Я использую его для обеспечения соблюдения этих символов в пароле. Спасибо.
Символ ^ (отрицание) используется для сопоставления того, что не входит в группу символов.
Это ссылка на Обычные выражения
Вот информация об отрицании:

Я вообще не понимаю, как это решает вопрос.
Обратите внимание, что это не экранирование самой строки, а оболочка с использованием
\Qи\E. Это может привести к неожиданным результатам, например,Pattern.quote("*.wav").replaceAll("*",".*")приведет к\Q.*.wav\E, а не.*\.wav, как вы могли ожидать.