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

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

8 ответов


С в Java 1.5, да:

Pattern.quote("");

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

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

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

Pattern.compile(textToFormat, Pattern.LITERAL);

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

посмотреть шаблон javadoc для детали.


во-первых, если

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

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

Я часто подключаю длинные строки текста .свойства файлы, а затем генерировать темы электронной почты и тела из них. Действительно, это, по-видимому, способ по умолчанию сделать 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])", "\\");
    }
}

узор.цитата ("blabla") работает хорошо.

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

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

этот метод возвращает: некоторые/\s / wText*/\,**

код, например, и тесты:

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

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

Регулярные Выражения