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 .