Вы когда-нибудь видели этот мем и вроде как соглашались с ним?

Что ж, тогда ты такой же, как я. И я, например, хотел бы это изменить. Эта статья призвана решить эту проблему и превратить ее в еще один инструмент, доступный в вашем арсенале разработчика. Я считаю, что им определенно можно злоупотреблять, однако бывают ситуации, когда это необходимо.

Давайте погрузимся в это.

Конструкции регулярных выражений

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

Скобки «[]» против скобок «()»

Скобки называются классом символов, а круглые скобки - группой захвата [1].

Класс символов - это способ сказать, какие символы вы хотите сопоставить. Например.

Здесь вывод будет следующий.

true
true
false
false

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

Здесь мы пытаемся сопоставить строку формата: DIGIT + DIGIT = DIGIT. И мы хотим извлечь цифры.

Первый шаблон использует только классы символов, «+» (который экранирован, потому что он имеет другое значение в регулярном выражении) и «=». Во втором шаблоне используются безымянные группы захвата. Последний и третий шаблоны используют именованные группы захвата.

Обратите внимание на синтаксис именованных групп захвата: (шаблон? ‹NAME›)

Результатом этого является следующий.

Number of groups: 0
true
Number of groups: 3
true
3+1=4
3
1
4
Number of groups: 3
true
3+1=4
3
1
4
3
1
4

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

Матчи против поиска

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

Давайте воспользуемся предыдущим примером попытки получить цифры из строк. Но в данном случае мы хотим просто получить цифры, нас не волнует общий формат строки. В этом случае мы можем снова использовать именованные группы захвата, но вместо этого использовать метод find. Нравится.

И вывод из этого следующий.

Number of groups: 1
3
3
3
1
1
1
4
4
4

Мы можем отметить, что первая группа с номером 0 всегда полностью совпадает с исходным шаблоном. И количество групп в основном 1+ определенных групп.

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

Квантификаторы

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

В этой статье я коснусь только жадного, но при необходимости проверьте и два других. Допустим, вы хотите найти последовательности цифр. Предположим, мы хотим обобщить наш предыдущий пример «ЦИФРА + ЦИФРА = ЦИФРА», чтобы учесть такие числа, что «100 + 50 = 150» также будет работать.

Я также использовал предопределенный символьный класс \ d, который просто означает цифру, вы можете найти еще несколько предопределенных классов здесь [1].

Значение «\\ d {1,}» означает, что должна быть хотя бы одна цифра. Вы можете дать ему другой аргумент, допустим, максимум 3, например, так: «\\ d {1,3}.

Оператор «ИЛИ»

Этот оператор может быть полезен, если вам нужно условное соответствие. Допустим, у нас есть такие строки, как «Оценка 5», «Оценка 2», «Оценка 3» и «Оценка 9». И нам нужно убедиться, что формат правильный, при извлечении цифры. Для этого мы можем использовать оператор или.

Результат здесь такой, как ожидалось.

true
Rating 5
5
true
Score 2
2
true
Scores 3
3
true
Point 9
9
false

Я добавил «s {0,1}», чтобы показать, что вы можете делать выражения внутри OR сколь угодно сложными.

Обратная ссылка

Допустим, у вас есть строки вроде следующего.

  • Яблоко: 3 яблока
  • Апельсин: 4 апельсина
  • Банан: 1 банан

По сути, вы хотите найти что-то вроде: «WORD: DIGIT WORD (s)»

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

Вы можете видеть, что я сослался на названную группу захвата «плод» в конце шаблона, используя синтаксис «\\ k ‹NAME›».

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

Компиляция паттернов

Использование функции совпадений в Pattern (см. Первый пример) фактически компилирует регулярное выражение и сопоставляет его в фоновом режиме. В других примерах явно использовался метод компиляции Pattern. Эта функция довольно дорогая, что я могу продемонстрировать ниже.

Итак, вы хотите повторно использовать его для вызовов методов, возможно, установить его как статическое конечное поле.

Я повторно использую последний пример с плодами и сделаю некоторый рефакторинг в методы. См. Пример ниже.

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

+------------------------------------+-----------------------------+
|           compileAlways            |            787 ms           |
+------------------------------------+-----------------------------+
|            compileOnce             |            105 ms           |
+------------------------------------+-----------------------------+

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

Я говорил об этом в предыдущих статьях, например, когда сравнивал LinkedList с ArrayList, и мои главные советы по выполнению микротестирования в Java см. По ссылкам ниже.





использованная литература

[1] Шаблон (Java SE 13 и JDK 13)
https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/regex/Pattern .html