Как экранировать текст для регулярного выражения в Java - PullRequest
303 голосов
/ 13 сентября 2008

Есть ли в Java встроенный способ экранирования произвольного текста, чтобы его можно было включить в регулярное выражение? Например, если мои пользователи введут «5 долларов», я бы хотел, чтобы это совпадало с точным, а не с 5 после окончания ввода.

Ответы [ 8 ]

422 голосов
/ 13 сентября 2008

С Java 1.5, да :

Pattern.quote("$5");
101 голосов
/ 13 сентября 2008

Разница между Pattern.quote и Matcher.quoteReplacement была неясна мне до того, как я увидел следующий пример

s.replaceFirst(Pattern.quote("text to replace"), 
               Matcher.quoteReplacement("replacement text"));
26 голосов
/ 14 марта 2016

Возможно, будет слишком поздно ответить, но вы также можете использовать Pattern.LITERAL, который игнорирует все специальные символы при форматировании:

Pattern.compile(textToFormat, Pattern.LITERAL);
13 голосов
/ 13 сентября 2008

Я думаю, что вы после этого \Q$5\E. Также см. Pattern.quote(s), представленный в Java5.

См. Шаблон Javadoc для деталей.

10 голосов
/ 14 августа 2012

Сначала, если

  • вы используете replaceAll ()
  • Вы НЕ используете Matcher.quoteReplacement ()
  • текст, который будет заменен, включает в себя $ 1

это не ставит 1 в конце. Он будет смотреть на регулярное выражение поиска для первой подходящей группы и подпункта THAT. Вот что означает $ 1, $ 2 или $ 3 в тексте замены: сопоставление групп из шаблона поиска.

Я часто вставляю длинные строки текста в файлы .properties, затем генерирую из них темы и сообщения электронной почты. Действительно, это, кажется, способ сделать i18n по умолчанию в Spring Framework по умолчанию. Я помещаю теги XML в качестве заполнителей в строки и использую replaceAll () для замены тегов XML значениями во время выполнения.

Я столкнулся с проблемой, когда пользователь вводил цифру в долларах и центах со знаком доллара. replaceAll () захлебнулся этим, в следовой строке появилось следующее:

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

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

6 голосов
/ 16 ноября 2012

Чтобы иметь защищенный шаблон, вы можете заменить все символы на «\\\\», кроме цифр и букв. И после этого вы можете вставить в этот защищенный шаблон ваши специальные символы, чтобы этот шаблон работал не как глупый цитируемый текст, а как паттерн, но как ваш. Без специальных символов пользователя.

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("\\\\$1");
        return str.replaceAll("([^a-zA-Z0-9])", "\\\\$1");
    }
}
3 голосов
/ 31 июля 2017

Pattern.quote ("blabla") работает хорошо.

Pattern.quote () работает хорошо. Он включает в себя предложение с символами " \ Q " и " \ E ", а также экранирование "\ Q" и "\ E" Однако, если вам нужно сделать реальное экранирование регулярного выражения (или пользовательское экранирование), вы можете использовать этот код:

String someText = "Some/s/wText*/,**";
System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));

Этот метод возвращает: Some / \ 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"));
0 голосов
/ 22 июня 2018
Символ

^ (отрицание) используется для сопоставления чего-либо, чего нет в группе символов.

Это ссылка на Регулярные выражения

Вот информация об изображении отрицания:

Info about negation

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...