Как избежать текста для регулярного выражения в Java

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

Ответ 2

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

s.replaceFirst(Pattern.quote("text to replace"), 
               Matcher.quoteReplacement("replacement text"));

Ответ 3

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

Pattern.compile(textToFormat, Pattern.LITERAL);

Ответ 4

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

Подробнее см. Pattern javadoc.

Ответ 5

Прежде всего, если

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

он не поместит 1 в конец. Он будет искать регулярное выражение поиска для первой сопоставимой группы и суб THAT. Что означает $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 input

вместо

msg = msg.replaceAll("<userInput \\/>", userInput);

с

msg = msg.replaceAll("<userInput \\/>", Matcher.quoteReplacement(userInput));

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

Ответ 6

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

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

Ответ 7

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