Регулярные выражения в Java: Мастерство сопоставления шаблонов с java.util.regex
Java предоставляет пакет java.util.regex для сопоставления шаблонов с помощью регулярных выражений. Регулярные выражения Java очень похожи на язык программирования Perl и довольно просты в изучении.
Основные классы пакета java.util.regex
Пакет java.util.regex в основном состоит из трёх классов:
- Pattern — объект Pattern представляет скомпилированное регулярное выражение. У класса нет публичных конструкторов. Для создания шаблона нужно вызвать один из статических методов
compile(), который принимает регулярное выражение и возвращает объект Pattern. - Matcher — объект Matcher — это механизм, интерпретирующий шаблон и выполняющий операции сопоставления во входной строке. Получить Matcher можно, вызвав метод
matcher()у объекта Pattern. - PatternSyntaxException — непроверяемое исключение, указывающее на синтаксическую ошибку в регулярном выражении.
Группы захвата (Capturing Groups)
Группы захвата позволяют рассматривать несколько символов как единое целое. Они создаются путём помещения символов в круглые скобки. Например, регулярное выражение (dog) создаёт одну группу, содержащую буквы «d», «o», «g».
Группы нумеруются по порядку открывающих скобок слева направо. В выражении ((A)(B(C))) существует четыре группы:
((A)(B(C)))— группа 0 (весь шаблон)(A)— группа 1(B(C))— группа 2(C)— группа 3
Метод groupCount() объекта Matcher возвращает количество групп захвата (не считая группу 0). Группа 0 всегда представляет всё выражение.
Пример: поиск цифр в строке
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
public static void main(String args[]) {
String line = "This order was placed for QT3000! OK?";
String pattern = "(.*)(\\d+)(.*)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(line);
if (m.find()) {
System.out.println("Found value: " + m.group(0));
System.out.println("Found value: " + m.group(1));
System.out.println("Found value: " + m.group(2));
} else {
System.out.println("NO MATCH");
}
}
}
Результат:
Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT300
Found value: 0
Синтаксис регулярных выражений
Таблица ниже содержит основные метасимволы и конструкции, доступные в Java:
| Подвыражение | Описание |
|---|---|
^ | Начало строки |
$ | Конец строки |
. | Любой одиночный символ, кроме новой строки (с флагом m — и новую строку) |
[...] | Любой одиночный символ из набора в скобках |
[^...] | Любой одиночный символ, не входящий в набор |
\A | Начало всей строки |
\z | Конец всей строки |
\Z | Конец строки, за исключением возможного завершающего перевода строки |
re* | 0 или более вхождений предыдущего выражения |
re+ | 1 или более вхождений |
re? | 0 или 1 вхождение |
re{n} | Ровно n вхождений |
re{n,} | Не менее n вхождений |
re{n,m} | От n до m вхождений |
a|b | Соответствует a или b |
(re) | Группа с запоминанием текста |
(?:re) | Группа без запоминания (незахватывающая) |
(?>re) | Независимая подмаска (без отката) |
\w | Символ слова (буквы, цифры, подчёркивание) |
\W | Не символ слова |
\s | Пробельный символ ([\t\n\r\f]) |
\S | Не пробельный символ |
\d | Цифра ([0-9]) |
\D | Не цифра |
\b | Граница слова (вне скобок) / backspace (внутри) |
\B | Не граница слова |
\n, \t, \r | Перевод строки, табуляция, возврат каретки |
\Q...\E | Экранирование всех символов между \Q и \E |
Основные методы класса Matcher
Методы индексов
| Метод | Описание |
|---|---|
start() | Начальный индекс предыдущего совпадения |
start(int group) | Начальный индекс подпоследовательности, захваченной указанной группой |
end() | Индекс после последнего символа совпадения |
end(int group) | Индекс после последнего символа подпоследовательности группы |
Методы поиска
| Метод | Описание |
|---|---|
lookingAt() | Пытается сопоставить начало входной последовательности с шаблоном |
find() | Ищет следующую подпоследовательность, соответствующую шаблону |
find(int start) | Сбрасывает матчер и ищет совпадение, начиная с указанного индекса |
matches() | Пытается сопоставить всю область с шаблоном |
Методы замены
| Метод | Описание |
|---|---|
replaceAll(String replacement) | Заменяет все вхождения, соответствующие шаблону |
replaceFirst(String replacement) | Заменяет только первое вхождение |
appendReplacement(StringBuffer sb, String replacement) | Незавершающий шаг добавления и замены |
appendTail(StringBuffer sb) | Завершающий шаг добавления и замены |
quoteReplacement(String s) | Возвращает литеральную строку замены для использования в appendReplacement |
Пример: подсчёт вхождений слова «cat»
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static final String REGEX = "\\bcat\\b";
private static final String INPUT = "cat cat cat cattie cat";
public static void main(String args[]) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
int count = 0;
while (m.find()) {
count++;
System.out.println("Match number " + count);
System.out.println("start(): " + m.start());
System.out.println("end(): " + m.end());
}
}
}
Результат:
Match number 1 start(): 0 end(): 3
Match number 2 start(): 4 end(): 7
Match number 3 start(): 8 end(): 11
Match number 4 start(): 19 end(): 22
Использование границ слова \b гарантирует, что «cat» не является частью более длинного слова (например, «cattie» не учитывается).
Пример: replaceFirst и replaceAll
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static String REGEX = "dog";
private static String INPUT = "The dog says meow. All dogs say meow.";
private static String REPLACE = "cat";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
INPUT = m.replaceAll(REPLACE);
System.out.println(INPUT);
}
}
Результат:
The cat says meow. All cats say meow.
Пример: appendReplacement и appendTail
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static String REGEX = "a*b";
private static String INPUT = "aabfooaabfooabfoob";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, REPLACE);
}
m.appendTail(sb);
System.out.println(sb.toString());
}
}
Результат:
-foo-foo-foo-
Класс PatternSyntaxException
Предоставляет методы для диагностики синтаксических ошибок:
| Метод | Описание |
|---|---|
getDescription() | Описание ошибки |
getIndex() | Индекс ошибки в шаблоне |
getPattern() | Ошибочный шаблон |
getMessage() | Многострочное сообщение с описанием, индексом, шаблоном и визуальным указанием позиции ошибки |
java
- Выражения, операторы и блоки в C#: подробное руководство с примерами
- Освоение операторов Java: типы, синтаксис и практические примеры
- Понимание выражений, операторов и блоков в Java
- Комментарии в Java: типы, использование и лучшие практики
- Освоение улучшенного цикла for в Java: синтаксис, примеры и лучшие практики
- Освоение строк в Java: создание, методы и лучшие практики
- Интерфейсы в Java: концепции, реализация и лучшие практики
- Try-with-resources в Java: автоматическое управление ресурсами
- Аннотации в Java: типы, размещение и практические примеры
- Assertions в Java: практическое руководство по обнаружению багов и обеспечению надежности кода