Перейти к основному содержимому

Понимание метода Pattern.quote

· 3 мин. чтения

1. Обзор

При использовании регулярных выражений в Java иногда нам нужно сопоставлять шаблоны регулярных выражений в их буквальной формебез обработки каких -либо метасимволов , присутствующих в этих последовательностях.

В этом кратком руководстве давайте посмотрим, как мы можем экранировать метасимволы внутри регулярных выражений как вручную, так и с помощью метода Pattern.quote() , предоставляемого Java.

2. Без экранирования метасимволов

Давайте рассмотрим строку, содержащую список сумм в долларах:

String dollarAmounts = "$100.25, $100.50, $150.50, $100.50, $100.75";

Теперь давайте представим, что нам нужно найти в нем вхождения определенной суммы долларов. Давайте соответствующим образом инициализируем строку шаблона регулярного выражения:

String patternStr = "$100.50";

Во-первых, давайте выясним, что произойдет, если мы выполним наш поиск по регулярному выражению без экранирования каких-либо метасимволов :

public void whenMetacharactersNotEscaped_thenNoMatchesFound() {
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(dollarAmounts);

int matches = 0;
while (matcher.find()) {
matches++;
}

assertEquals(0, matches);
}

Как мы видим, сопоставитель не может найти ни одного вхождения $150,50 в нашей строке DollarAmounts . Это просто из-за того, что patternStr начинается со знака доллара , который является метасимволом регулярного выражения , указывающим конец строки .

Как вы, вероятно, должны были догадаться, мы столкнемся с одной и той же проблемой для всех метасимволов регулярных выражений. Мы не сможем искать математические операторы, которые содержат знаки вставки (^) для показателей степени, например « 5^3 », или текст, в котором используется обратная косая черта (), например « users\bob ».

3. Игнорировать метасимволы вручную

Итак, во-вторых, давайте избежим метасимволов в нашем регулярном выражении , прежде чем мы выполним наш поиск:

public void whenMetacharactersManuallyEscaped_thenMatchingSuccessful() {
String metaEscapedPatternStr = "\\Q" + patternStr + "\\E";
Pattern pattern = Pattern.compile(metaEscapedPatternStr);
Matcher matcher = pattern.matcher(dollarAmounts);

int matches = 0;
while (matcher.find()) {
matches++;
}

assertEquals(2, matches);
}

На этот раз мы успешно выполнили наш поиск ; Но это не может быть идеальным решением по нескольким причинам:

  • Конкатенация строк выполняется при экранировании метасимволов, которые усложняют отслеживание кода.
  • Менее чистый код из-за добавления жестко закодированных значений.

4. Используйте Pattern.quote()

Наконец, давайте рассмотрим самый простой и чистый способ игнорировать метасимволы в наших регулярных выражениях.

Java предоставляет метод quote() внутри своего класса Pattern для получения буквального шаблона строки:

public void whenMetacharactersEscapedUsingPatternQuote_thenMatchingSuccessful() {
String literalPatternStr = Pattern.quote(patternStr);
Pattern pattern = Pattern.compile(literalPatternStr);
Matcher matcher = pattern.matcher(dollarAmounts);

int matches = 0;
while (matcher.find()) {
matches++;
}

assertEquals(2, matches);
}

5. Вывод

В этой статье мы рассмотрели, как мы можем обрабатывать шаблоны регулярных выражений в их буквальных формах.

Мы увидели, как отсутствие экранирования метасимволов регулярных выражений не дало ожидаемых результатов и как экранирование метасимволов внутри шаблонов регулярных выражений можно выполнить вручную и с помощью метода Pattern.quote() .

Полный исходный код для всех использованных здесь примеров кода можно найти на GitHub .