Понимаем и используем группы захвата в Java regex
При создании групп захвата в регулярных выражениях Java используйте круглые скобки «(\d+)-(\w+)» , чтобы определить две группы: для чисел (\d+) и букв (\w+) . Обработка данных групп происходит через классы Pattern и Matcher :
Скопировать код
Pattern pattern = Pattern.compile("(\\d+)-(\\w+)"); Matcher matcher = pattern.matcher("123-abc"); if (matcher.find()) < String digits = matcher.group(1); // 123 — . захвачено! String letters = matcher.group(2); // "abc" — . успешно захвачено! >
Отметим, что matcher.group(1) и matcher.group(2) возвращают содержимое соответствующих групп.
Разбираемся с квантификаторами и способами захвата
Квантификаторы: жадные, ленивые и ревнивые типы
Квантификаторы определяют, сколько символов, соответствующих шаблону, надо захватить:
- Жадные ( * ): пытаются захватывать максимальное количество символов.
- Ленивые ( *? ): стремятся захватить минимальное количество символов.
- Ревнивые ( *+ ): работают аналогично жадным, но не допускают возврата.
Тип квантификатора определяет способ действия группы захвата в выражении.
Принцип «слева направо»
Порядок обработки и захвата регулярных выражений происходит слева направо. Так, первая группа будет захвачена раньше второй и так далее.
Обратные ссылки и именованные группы
Обратные ссылки ( \1 , \2 и т.д.) позволяют сослаться на уже захваченные группы. В версиях Java 7 и выше доступна возможность использования именованных групп посредством (?. ) , что улучшает читабельность кода.
Обеспечение точного соответствия
Незахватывающие группы
Незахватывающие группы (. ) позволяют применить квантификаторы, не захватывая содержимое.
Три основных строительных блока
Точка (.), звёздочка (*), и плюс (+) используются для обозначения различных комбинаций символов в регулярных выражениях.
Крайние случаи
Следует учесть такие экстремальные ситуации как совпадения нулевой длины, перекрывающиеся совпадения и ошибочные захваты.
Визуализация
Для наглядного представления работы регулярных выражений удобно использовать аналогию с «отрядом захватчиков»:
Matcher find java как работает
Регулярные выражения представляют мощный инструмент для обработки строк. Регулярные выражения позволяют задать шаблон, которому должна соответствовать строка или подстрока.
Некоторые методы класса String принимают регулярные выражения и используют их для выполнения операций над строками.
split
Для разделения строки на подстроки применяется метод split() . В качестве параметра он может принимать регулярное выражение, которое представляет критерий разделения строки.
Например, разделим предложение на слова:
String text = «FIFA will never regret it»; String[] words = text.split(«\\s*(\\s|,|!|\\.)\\s*»); for(String word : words)
Для разделения применяется регулярное выражение «\\s*(\\s|,|!|\\.)\\s*». Подвыражние «\\s» по сути представляет пробел. Звездочка указывает, что символ может присутствовать от 0 до бесконечного количества раз. То есть добавляем звездочку и мы получаем неопределенное количество идущих подряд пробелов — «\\s*» (то есть неважно, сколько пробелов между словами). Причем пробелы может вообще не быть. В скобках указывает группа выражений, которая может идти после неопределенного количества пробелов. Группа позволяет нам определить набо значений через вертикальную черту, и подстрока должна соответствовать одному из этих значений. То есть в группе «\\s|,|!|\\.» подстрока может соответствовать пробелу, запятой, восклицательному знаку или точке. Причем поскольку точка представляет специальную последовательность, то, чтобы указать, что мы имеем в виду имеено знак точки, а не специальную последовательность, перед точкой ставим слеши.
Соответствие строки. matches
Еще один метод класса String — matches() принимает регулярное выражение и возвращает true, если строка соответствует этому выражению. Иначе возвращает false.
Например, проверим, соответствует ли строка номеру телефона:
String input = «+12343454556»; boolean result = input.matches(«(\\+*)\\d»); if(result) < System.out.println("It is a phone number"); >else
В данном случае в регулярном выражение сначала определяется группа «(\\+*)». То есть вначале может идти знак плюса, но также он может отсутствовать. Далее смотрим, соответствуют ли последующие 11 символов цифрам. Выражение «\\d» представляет цифровой символ, а число в фигурных скобках — — сколько раз данный тип символов должен повторяться. То есть мы ищем строку, где вначале может идти знак плюс (или он может отсутствовать), а потом идет 11 цифровых символов.
Класс Pattern
Большая часть функциональности по работе с регулярными выражениями в Java сосредоточена в пакете java.util.regex .
Само регулярное выражение представляет шаблон для поиска совпадений в строке. Для задания подобного шаблона и поиска подстрок в строке, которые удовлетворяют данному шаблону, в Java определены классы Pattern и Matcher .
Для простого поиска соответствий в классе Pattern определен статический метод boolean matches(String pattern, CharSequence input) . Данный метод возвращает true, если последовательность символов input полностью соответствует шаблону строки pattern:
import java.util.regex.Pattern; public class StringsApp < public static void main(String[] args) < String input = "Hello"; boolean found = Pattern.matches("Hello", input); if(found) System.out.println("Найдено"); else System.out.println("Не найдено"); >>
Но, как правило, для поиска соответствий применяется другой способ — использование класса Matcher.
Класс Matcher
Рассмотрим основные методы класса Matcher:
- boolean matches() : возвращает true, если вся строка совпадает с шаблоном
- boolean find() : возвращает true, если в строке есть подстрока, которая совпадает с шаблоном, и переходит к этой подстроке
- String group() : возвращает подстроку, которая совпала с шаблоном в результате вызова метода find. Если совпадение отсутствует, то метод генерирует исключение IllegalStateException .
- int start() : возвращает индекс текущего совпадения
- int end() : возвращает индекс следующего совпадения после текущего
- String replaceAll(String str) : заменяет все найденные совпадения подстрокой str и возвращает измененную строку с учетом замен
Используем класс Matcher. Для этого вначале надо создать объект Pattern с помощью статического метода compile() , который позволяет установить шаблон:
Pattern pattern = Pattern.compile("Hello");
В качестве шаблона выступает строка «Hello». Метод compile() возвращает объект Pattern, который мы затем можем использовать в программе.
В классе Pattern также определен метод matcher(String input) , который в качестве параметра принимает строку, где надо проводить поиск, и возвращает объект Matcher :
String input = "Hello world! Hello Java!"; Pattern pattern = Pattern.compile("hello"); Matcher matcher = pattern.matcher(input);
Затем у объекта Matcher вызывается метод matches() для поиска соответствий шаблону в тексте:
import java.util.regex.Matcher; import java.util.regex.Pattern; public class StringsApp < public static void main(String[] args) < String input = "Hello"; Pattern pattern = Pattern.compile("Hello"); Matcher matcher = pattern.matcher(input); boolean found = matcher.matches(); if(found) System.out.println("Найдено"); else System.out.println("Не найдено"); >>
Рассмотрим более функциональный пример с нахождением не полного соответствия, а отдельных совпадений в строке:
import java.util.regex.Matcher; import java.util.regex.Pattern; public class StringsApp < public static void main(String[] args) < String input = "Hello Java! Hello JavaScript! JavaSE 8."; Pattern pattern = Pattern.compile("Java(\\w*)"); Matcher matcher = pattern.matcher(input); while(matcher.find()) System.out.println(matcher.group()); >>
Допустим, мы хотим найти в строке все вхождения слова Java. В исходной строке это три слова: «Java», «JavaScript» и «JavaSE». Для этого применим шаблон «Java(\\w*)». Данный шаблон использует синтаксис регулярных выражений. Слово «Java» в начале говорит о том, что все совпадения в строке должны начинаться на Java. Выражение (\\w*) означает, что после «Java» в совпадении может находиться любое количество алфавитно-цифровых символов. Выражение \w означает алфавитно-цифровой символ, а звездочка после выражения указывает на неопределенное их количество — их может быть один, два, три или вообще не быть. И чтобы java не рассматривала \w как эскейп-последовательность, как \n, то выражение экранируется еще одним слешем.
Далее применяется метод find() класса Matcher, который позволяет переходить к следующему совпадению в строке. То есть первый вызов этого метода найдет первое совпадение в строке, второй вызов найдет второе совпадение и т.д. То есть с помощью цикла while(matcher.find()) мы можем пройтись по всем совпадениям. Каждое совпадение мы можем получить с помощью метода matcher.group() . В итоге программа выдаст следующий результат:
Java JavaScript JavaSE
Замена в строке
Теперь сделаем замену всех совпадений с помощью метода replaceAll() :
String input = "Hello Java! Hello JavaScript! JavaSE 8."; Pattern pattern = Pattern.compile("Java(\\w*)"); Matcher matcher = pattern.matcher(input); String newStr = matcher.replaceAll("HTML"); System.out.println(newStr); // Hello HTML! Hello HTML! HTML 8.
Также надо отметить, что в классе String также имеется метод replaceAll() с подобным действием:
String input = "Hello Java! Hello JavaScript! JavaSE 8."; String myStr =input.replaceAll("Java(\\w*)", "HTML"); System.out.println(myStr); // Hello HTML! Hello HTML! HTML 8.
Разделение строки на лексемы
С помощью метода String[] split(CharSequence input) класса Pattern можно разделить строку на массив подстрок по определенному разделителю. Например, мы хотим выделить из строки отдельные слова:
import java.util.regex.Pattern; public class StringsApp < public static void main(String[] args) < String input = "Hello Java! Hello JavaScript! JavaSE 8."; Pattern pattern = Pattern.compile("[ . ]"); String[] words = pattern.split(input); for(String word:words) System.out.println(word); >>
И консоль выведет набор слов:
Hello Java Hello JavaScript JavaSE 8
При этом все символы-разделители удаляются. Однако, данный способ разбивки не идеален: у нас остаются некоторые пробелы, которые расцениваются как лексемы, а не как разделители. Для более точной и изощренной разбивки нам следует применять элементы регулярных выражений. Так, заменим шаблон на следующий:
Pattern pattern = Pattern.compile("\\s*(\\s|,|!|\\.)\\s*");
Теперь у нас останутся только слова:
Hello Java Hello JavaScript JavaSE 8
Далее мы подробнее рассмотрим синтаксис регулярных выражений и из каких элементов мы можем создавать шаблоны.
Java Matcher find is false but matches is true [закрыт]
Вопрос вызван проблемой, которая больше не воспроизводится, или опечаткой. Хотя похожие вопросы могут быть уместны на этом сайте, решение для этого вопроса вряд ли поможет будущим посетителям. Обычно можно избежать подобных вопросов написанием и исследованием минимальной программы для воспроизведения проблемы до публикации вопроса.
Закрыт 1 год назад .
Я попытался разобрать строку с помощью регулярного выражения, но столкнулся с каким-то странным поведением
System.out.println(m.matches()); //returns true System.out.println(m.find()); //returns false
Похоже, у меня есть несколько ошибок в моем регулярном выражении. Весь код приведен ниже
import java.util.regex.Matcher; import java.util.regex.Pattern; public class testRegexp < public static void main(String[] args) < String string = "Alexandr TheMakedonian 32"; Pattern pattern = Pattern.compile("(.*)\\s(.*)\\s(.*)"); Matcher m = pattern.matcher(string); System.out.println(m.matches()); System.out.println(m.find()); System.out.println(m.groupCount()); if( m.find() && m.groupCount() >= 3) < String firstName = m.group(1); String secondName = m.group(2); String ages = m.group(3); System.out.println(firstName); System.out.println(secondName); System.out.println(ages); >> >
Отслеживать
Serg Sergy
задан 20 июн 2022 в 15:29
Serg Sergy Serg Sergy
9 3 3 бронзовых знака
Please translate your question to the Russian language, because this segment of SO is for the Russian-speaking people
20 июн 2022 в 15:31
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вызов String.matches() сравнивает целую строку с шаблоном и после этого позиция для нового поиска перемещается в конец и соответственно последующий вызов find вернёт false , так как будет сравниваться пустая строка с шаблоном, в котором есть как минимум два пробела.
Если к примеру переставить вызовы данных методов местами или «сбросить» поиск при помощи Matcher::reset , оба вызова вернут true :
System.out.println(m.find()); // true System.out.println(m.matches()); // true Matcher m1 = pattern.matcher(string); System.out.println(m1.matches()); // true m1.reset(); System.out.println(m1.find()); // true
Регулярные выражения в Java

Концепция регулярных выражений возникла еще в 1950-х. Это способ поиска информации в строках с помощью шаблонов, записанных спецсимволами.
Технологию впервые использовал разработчик систем Unix Кен Томпсон в текстовом редакторе ed в 1968 году.
Java часто применяют для работы с регулярными выражениями: их поддержка — часть стандартной библиотеки java.util.regex.
Разобрались, что такое регулярные выражения в Java и как они помогают обрабатывать большие массивы строчных данных.
Что такое регулярные выражения
Для простых операций по обработке текстовой информации в языке Java можно использовать маски имен файлов. Таким способом легко скопировать все файлы, которые начинаются с буквы R.
Регулярные выражения — более продвинутый способ поиска соответствий или ошибок в тексте. Это набор символов (шаблон), который ищет соответствия в файле. Их часто применяют для обработки текста или редактирования, а также в создании скриптов для проверки на валидность. Например, чтобы проверить, отвечает ли заданный пароль условиям сервиса.
Классы библиотеки регулярных выражений
Пакет java.util.regex состоит из набора классов, которые применяют для согласования последовательностей символов с шаблонами, заданных выражениями.
Есть три ключевых класса:
- Pattern — набор команд и точка доступа к API регулярных выражений на Java.
- Matcher — класс, который сопоставляет результаты расшифровки класса Pattern с остальной частью программы.
Основные методы Matcher:
- 1. boolean matches выдает значение true, когда строка соответствует шаблону (Pattern);
- 2. boolean find выдает значение true, когда в строке есть подстрока, которая соответствует шаблону;
- 3. string group выдает подстроку, которая совпала с шаблоном после вызова метода find;
- 4. string replaceAll(String str) меняет все строки, соответствующие шаблону, и выдает результат с изменениями.
- PatternSyntaxException срабатывает в случае исключений (синтаксических ошибок).
Класс Pattern используют для задания регулярного выражения, а Matcher находит в коде последовательности символов.
статьи по теме:
Какие инструменты разработки используют чаще других.
Инженеры из Amazon и Sterlix GmbH делятся опытом.
Синтаксис регулярных выражений Java
Регулярные выражения записывают с помощью обычных символов, наборов символов и групповых символов.
Проще всего — поиск обычных текстовых символов. Символы, которые обозначают сами себя, называют литералами. Например, если в шаблон задать слово dog, то он будет искать в строке все случаи, когда слова начинаются с этих символов. Например, слова dog и doghunter попадут в выдачу.
Квадратные скобки и циркумфлекс (^) отображают не собственный символ, а команду. Такие символы называют метасимволами или спецсимволами. Если разместить символ ^ в квадратных скобках ( [^dog] ), то matcher будет искать все символы, кроме буквосочетания dog.
Метасимволы для поиска соответствий и границ строк
- ^ — начало строки;
- $ — конец строки;
- — — задать один символ, которого не должно быть в скобках;
- \b — конец слова;
- \B — не конец слова;
- \A — начало ввода;
- \Z — конец ввода.
Классы символов
Регулярные выражения позволяют работать с классами символов. Например:
- \d — любой цифровой символ;
- \D — любой нецифровой;
- \s — символ пробела;
- \S — непробельный символ;
- . — задать один произвольный символ;
- \w — буквенно-цифровой символ;
- \W — любой символ, кроме буквенно-цифрового.
Задать диапазон символов можно с помощью символа -. Тогда регулярное выражение (a-z) будет искать все символы в диапазоне.
Некоторые команды начинаются с обратной косой черты \. Это значит, что следующий символ используют как спецсимвол. Например, сочетание косой черты и символа n — \n — будет означать перенос строки.
Иногда нужно экранировать символы, то есть вывести на экран знаки, которые программа обычно воспринимает как системные. Так, знак + обозначает появление другого символа один и более раз. Чтобы отобразить на экране сам плюс, нужно использовать две косые черты: \\+, так как одинарная косая черта \ тоже является спецсимволом.
Прогнозирование и анализ временных рядов
Data Scientist в Holidu
Архитектура высоких нагрузок
Software Engineer в Amazon
Квантификаторы и режимы их работы
В регулярных выражениях есть ограничители, которые определяют частоту появления символа или их группы. Такие ограничители называют квантификаторами. Записывают их после символа или группы символов.
Основные квантификаторы:
- ? — символ появляется ноль или один раз;
- * — ноль или более раз;
- + — один или более раз;
- — n раз;
- — n и более;
- — не меньше n, но не более m раз.
Квантификаторы работают в трех режимах: жадном, ленивом и сверхжадном. По умолчанию регулярные выражения работают в жадном режиме.
- В жадном режиме программа ищет максимальные совпадения по длине строки.
- Жадный режим выполняет поиск по строке слева направо, а потом наоборот. Сверхжадный не возвращается назад.
- Отличие сверхжадного режима от жадного — в реверсивном поиске.
- Ленивый режим ищет наиболее короткое совпадение, которое выполняет все условия шаблона.
Как используют regex в Java
Мы рассказывали, что регулярные выражения применяют для редактуры строк на основе шаблонов. Например, можно автоматически заменить кавычки-лапки “ ” на кавычки-елочки « », проверить правильное написание слов или количество открытых и закрытых скобок.
Также регулярные выражения используют для валидации. Например, чтобы проверить, отвечает ли IP-адрес десятичному виду, содержит ли электронный адрес символ @ и доменное имя.
Символы в регулярных выражениях комбинируются. Java regex для определения валидности телефонного номера выглядит так:
Здесь указаны следующее команды:
- Номер может начинаться с необязательного знака « ( »;
- Далее следуют 3 цифры от 0 до 9;
- Строка может иметь необязательный символ « — » между цифрами;
- В строке может быть еще один необязательный символ « — »;
- Еще один диапазон из 3 цифр от 0 до 9;
- Необязательный символ « — »
- Еще 4 цифры от 0 до 9.
Такие выражения сложно интерпретировать, но они упрощают выполнение программ и не требуют прописывать многострочный код с большим количеством условий.
Чтобы упростить работу, существуют статистические анализаторы регулярных выражений.
С Java работает онлайн-анализатор Regex101. Он поддерживает восьмую версию языка и способен интерпретировать регулярные выражения, протестировать код и воспользоваться библиотекой готовых решений.