Регулярные выражения в Java
Регулярные выражения представляют собой шаблон в виде набора символов или одного из них, который сравнивают со строкой и находят совпадения. Регулярные выражения используют для поиска определенных строк. Найденное совпадение по шаблону сохраняется в переменную, со значением которой можно проводить дальнейшие манипуляции.
Регулярные выражения являются объектами классов Pattern и Matcher. Эти классы являются частью пакета java.util.regex, который предоставляет основной функционал для работы с регулярными выражениями. Они же предоставляют набор статических методов для поиска совпадений в строке. Совпадения возвращаются в виде различных типов данных, в зависимости от используемого метода: Int, String, Boolean. Сам шаблон для поиска является объектом типа Pattern или Matcher и сохраняется в переменную одного из данных типов.
Синтаксис регулярных выражений
Шаблон регулярного выражения может быть представлен в 2-х видов:
- Сплошная строка. Шаблон в виде строки «Google» совпадает со строкой «Google».
- Строка с ограничителями. В качестве ограничителей используются специальные символы: квантификаторы, диапазоны, символы исключения (метасимволы). К примеру, в строке «Google» нужно найти часть слова после первого символа «o», шаблон будет выглядеть следующим образом: «o(\\w*)». Результатом станет «oogle». Здесь «\W*» метасимвол, который говорит о том, что после «о» может находиться сколько угодно символов. Метасимволы и другие специальные конструкции отделяются скобками.
Часто для указания шаблона используется не один специальный символ, а серия: «(^[fa])(\\D)»- найдет все совпадения, в которых отсутствует «fa» и в которых отсутствуют цифры.
Как работать с регулярными выражениями
Как уже упоминалось ранее, регулярные выражения являются объектами классов Pattern и Matcher. Поэтому, чтобы иметь возможность создавать соответствующие объекты, необходимо импортировать пакет java.util.regex.Pattern. Однако одного паттерна недостаточно и требуется импорт обеих классов. Что работать сразу с двумя, требуется ниже добавить java.util.regex.Matcher. Без импорта нельзя обращаться к несуществующим классам. Ведь методы класса Pattern создают и сохраняют шаблон, а методы класса Matcher находят и сохраняют совпадения.
Пример с шаблоном в виде простой строки:
importSystem.out; \\Импортирован класс out, чтобы не писать полную конструкцию для вывода строк в консоль.
public class FindMatch {
public static void Main(String[] args) {
Stringstr = «Train»; \\ Исходная строка в которой будет вестись поиск
Patternp = Pattern.compile(str);\\ Инициализация объекта шаблона
Matcherm = p.matcher(str); \\ Сохранение результата сравнения
println(m.matches()) \\ Вывод результат выполнения метода, который отобразит true
}
}
Пояснение к примеру:
- До объявления главного класса были импортированы классы Pattern и Matches.
- Инициализация строки str значением «Train».
- Сохранение в объект pattern класса Pattern результата статического метода этого же класса compile c параметром, он же шаблон «Train».
- Сохранение в объект matcher класса Matcher результата статического метода объекта pattern. Метод matcher принимает в качестве аргумента переменную str и сравнивает ее значение со значением объекта p. Если шаблон и значение совпадают, то возвращается объект класса Matcher c результатом сравнения.
- Результат выводится на экран с помощью метода matches() и равен true.
Пример с метасимволом:
ImportSystem.out;
public static void Main(String[] args) {
String s = «First Place! Second PlacePlace! Place№ 6.»;
Pattern p = Pattern.compile(«Place(\\w*)»);
Matcher m = pattern.matcher(s);
while(m.find()) \\ Пока совпадения находятся, итерации цикла будут выполняться
print(m.group()); // Первый вывод Place, второйPlacePlace, третий Place
}
Пояснение к примеру:
- Сохранение в строковую переменную значения «FirstPlace! SecondPlacePlace! Place№ 6.».
- Сохранение шаблона «Java(\\w*)» в переменную pattern, который возвращает статический метод compile(). Здесь в строке будут искаться все значения «Java» с буквенными символами, которые идут после них, пунктуация, числа и пробелы будут игнорироваться за счет метасимвола \w*, находящегося в шаблоне.
- Результат совпадения сохраняется в объект m класса Match.
- Цикл While будет выполняться до тех пор, пока метод find() будет находить совпадения в строке.
- При каждом срабатывании find(), будет выводиться на экран результат метода group() в виде строки совпадения. Данный метод срабатывает только при положительном результате, возвращаемым методом find().
- Результатом вывода станет три совпадения, а на экране отобразится строка «PlacePlacePlacePlace№ 6».
Не обязательно всегда сохранять строку для сравнения с шаблоном. Метод mather() в качестве аргумента может принимать не переменную, а строку — matcher(«Place»).
Группы шаблонов
Можно установить, как один шаблон для поиска, так и их группу, сохранив ее в один объект класса Pattern. Группа шаблонов помещается в круговые скобки и выглядит следующим образом: ((pattern1) (pattern2)).
Здесь в первой скобке организовывается первый шаблон в виде специального символа, во второй скобке второй другой шаблон. Вне скобок можно помещать строку или специальный символ. В итоге, будет искаться соответствие по первому и второму шаблону. Если хоть один из них не совпадает, то метод find() вернет false.
Вывод результата на экран или проверка строки на соответствие осуществляется через цикл, или проверяется на соответствие с помощью метода group(0). В качестве аргумента данного метода используется числовой индекс скобок — первая скобка равна 0, вторая 1 и так далее.
Методы класса Pattern
- Pattern.pattern() — статический метод, который возвращает строковое представление шаблона регулярного выражения.
- Pattern.compile(regsp, param) — статический метод, который сохраняет шаблон в объект класса Pattern или Matcher. Первый параметр обязательный и является шаблоном. Второй необязательный может быть трех видов: CASE_INSENSITIVE — игнорирует регистр символов; LITERAL — специальные символы строки, такие как пробелы или пунктуация, становятся обычными; UNICODE_CASE — игнорирует регистр символов формата unicode.
- Pattern.matches(regexp, charseq) — возвращает true или false если шаблон regexp соответствует строке или символу charseq.
- Pattern.split(charseq, limit) — делит текст строки на массив символов типа String, переданный в параметр charseq. Параметр лимит задает количество совпадений, которое должно быть найдено в первом параметре, где: limit> 0 — поиск совпадений по числу; limit< 0 — поиск всех совпадений до конца строки; limit = 0 — ищет все совпадения кроме пустых символов в конце строки.
- patt.matcher(string) — проводит поиск в строке параметра string и возвращает результат как объект класса Matcher.
Методы класса Matcher
- Pattern.compile(«шаблон») — создается шаблон и сохраняется в объект Mather.
- pat.matches() — если вся строка совпадает с шаблоном, то возвращает true, в противном случае false.
- pat.find() — возвращает true, если в строке была найдена подстрока, соответствующая шаблону. Если совпадений несколько, то метод после обнаружения первого совпадения, после повторного вызова находит следующее совпадение.
- pat.group() — метод возвращает совпадение в строковом формате после положительного результата вызова метода find(). При отсутствии совпадения, метод создает исключение IllegalStateException.
- pat.start() — также в зависимости от порядка найденного совпадения методом find(), метод start() возвращает индекс совпадения, начиная с начала строки.
- pat.end() — метод аналогичен предыдущему, только возвращает индекс следующего совпадения, после найденного текущего.
- pat.replaceAll(string) — метод осуществляет замену всех текущих совпадений на строку в параметре string и возвращает измененную строку, сохраняя ее в переменную класса String.
Список всех специальных символов
В любом языке программирования, где есть возможность использовать регулярные выражения, присутсвует внушительный перечень специальных символов для создания сложных шаблонов. Java не стал исключением и также пользуется большинством специальных символов, присутствующих C-подобных языках.
Метасимволы
Метасимволы указывают место поиска подстроки и формат соответствия:
- ^ — ищет совпадения в начале строки и игнорирует регистр букв.
- $ — ищет совпадения в конце строки, игнорируя регистр.
- . — находит любой отдельный символ.
- | — отделитель шаблонов, находящий соответствие любого из них. К примеру, dog|cat|bird — находит совпадение с одной или несколькими строками шаблона.
- \A — поиск совпадений в начале строки, false если находит в конце.
- \z — поиск в конце строки.
- \w — ищет совпадение только по буквенным символам.
- \W — ищет совпадения только не по буквенным символам.
- \s — находит с пробелами.
- \S — находит без пробелов.
- \d — находит с цифрами.
- \D — исключает цифры.
- \G — находит точку конца последнего совпадения.
- \b — возвращает строку в скобках.
- \n — совпадает переводу строки.
Квантификаторы
Квантификаторы создают шаблон для поиска отдельного символа, очереди и ограничивают их количество, а также меняют порядок поиска:
- r* — здесь «r» выступает в роли шаблона, а «*» говорит о том, что искать нужно все совпадения до конца строки.
- r+ — знак «+» говорит о том, что совпадений должно быть не менее одного.
- r? — соответствует одному совпадению символов или одного символа «r».
- r{x} — соответствует символам «r», которые пишутся слитно x-раз.
- r{x,y} — совпадает от x до y.
- r{x,} — ищет совпадения, где символ «r» пишется слитно не менее x-раз.
Скобки
Скобочные конструкции предоставляют дополнительные опции для поиска:
- […] — соответствует любому отдельному символу, находящемуся в скобках.
- [^…] — исключает поиск символа, находящегося в скобках.
Примеры использования специальных символов
Допустим есть строка «Hello World2020»:
- «(([h])(\\A))» найдет «H»;
- «(([0])(\\z))» найдет символ «0» в конце строки.
- «[o]*» найдет «o, o».
- «[^l]{2}» найдет «H, e, o, W, o, r, l, d, 2, 0, 2, 0».
Лучшие источники информации по регулярным выражениям Java
Существуют отдельные печатные издания, которые предоставляют общую информацию о регулярных выражениях:
- Лойан Гронер, Габриэль Манрикс «Регулярные выражения в JavaScript».
- Майкл Фицжеральд «Введение в регулярные выражения».
- Фридл Дж. «Регулярные выражения».
- Гойвертс Я., Левитан С. «Регулярные выражения. Сборник рецептов».
- ChildDave. «Шпаргалка по регулярным выражениям».
Рекомендуемые ресурсы:
- W3Cschools.com — сайт предоставляет информацию по основам Java, а также регулярным выражениям для этого языка и других.
- javarush.ru — также предоставляет уроки изучения Java и отдельно описание работы с регулярными выражениями.
- javahelp.online — подробно на простых примерах описываются приемы использования простых и сложных шаблонов.
В целом для изучения регулярных выражений Java подойдет любой учебник, описывающий общую концепцию регулярных выражений. Остается только вникнуть в функциональность классов Pattern и Matcher, которые были разработаны исключительно для Java. Стоит отметить, что если не использовать среду разработки для написания кода, а ограничиваться лишь консолью, то пакет java.util.regex придется загружать отдельно, чтобы можно было подключить соответствующие классы.
Применение шаблонов значительно сокращает исходный текст кода. При работе со строковыми методами и поиска слов в строке, следовало бы применять циклы для перебора строк. Шаблоны позволяют выполнить поиск в несколько строк кода и не требуют от программиста продумывания сложных алгоритмов, которые снижают производительность программы.