Мощные regex для практичных разработчиков

0
616
views

Перевод статьи «Powerful regex for the practical dev».

Photo by Crew on Unsplash

Regex (регулярные выражения, англ. regular expressions) — это поиск на стероидах. В этом посте я на примерах покажу, как задавать эффективные условия поиска.

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

Для примеров мы будем использовать следующий текст (демо):

Alabama (AL) Birmingham (Dec 14, 1819) 4,903,185
Hawaii* (HI) Honolulu (Aug 21, 1959) 1,415,872
Michigan (MI) Detroit (Jan 26, 1837) 9,986,857
North Dakota (ND) Fargo (Nov 2, 1889) 762,062
Wyoming* (WY) Cheyenne (Jul 10, 1890) 578,759

(штат, его id, крупнейший город штата, дата основания и количество населения)

Как пользоваться этим руководством

  • Бегло просмотрите картинки и заголовки. В статье много примеров.
  • Если вы новичок, читайте с начала, не перескакивайте.
  • Найдите наиболее интересные для себя примеры.
  • Примеры, расположенные по соседству, связаны между собой.
  • Поэкспериментируйте с примерами самостоятельно.
  • Найдите шпаргалку внизу статьи.

Настройка

Откройте свою IDE или пройдите по ссылке.

  • Откройте современную IDE (я использую VSCode)
  • Вставьте пример
  • Откройте поиск (ctrl + f или cmd + f)
  • Включите regex (обычно значок .*).

Базовые шаблоны поиска

Буквы — [a-zA-Z]

  • [a-z] — буквы в нижнем регистре.
  • [A-Z] — буквы в верхнем регистре.
  • В VSCode регистр имеет значение, только если включена опция «match case» (Aa).

Найдено 102 совпадения с шаблоном, потому что шаблон — все буквы.

Слова — [a-zA-Z]+

  • [a-zA-Z] — буквы.
  • + — это квантификатор, означающий, что символ из указанного набора может повторяться один раз и более. Таким образом мы показываем, что ищем не каждую конкретную букву, а отдельные последовательности букв.

Найдено 21 соответствие с шаблоном поиска, потому что именно столько слов в нашем тексте.

Определенные слова — (Jan|Jul|Dec)

Шаблон (Jan|Jul|Dec) дает совпадение не со всеми словами, а именно с Jan, Jul или Dec.

Двузначные числа — [0-9]{2}

  • [0-9] — цифры.
  • {2} — это квантификатор, показывающий, сколько цифр из набора должно идти подряд.

Обратите внимание, что в примере с шаблоном совпали и четырехзначные числа. На самом деле каждое такое число — два последовательных двузначных числа.

Четырехзначные числа — [0-9]{4}

  • [0-9] — цифры.
  • {4} — квантификатор, показывающий, что мы ищем 4 последовательно идущие цифры.

2-3 буквы, идущие подряд — [a-z]{2,3}

  • [a-z] — буквы.
  • {2,3} — квантификатор, в котором задан диапазон от 2 до 3. То есть мы ищем последовательно идущие 2-3 буквы.

Обратите внимание, что с шаблоном совпали длинные слова. Как и в предыдущем примере с цифрами, это означает, что в каждом таком слове есть несколько совпадений.

Слова из 6 и более букв — [a-z]{6,}

  • [a-z] — буквы.
  • {6,} — квантификатор, в котором указан только нижний лимит. То есть, мы ищем последовательности из шести и более букв.

Три последовательно идущие буквы и/или цифры — \w{3}

  • \w — означает «буквы или цифры» (см. шпаргалку внизу статьи).
  • {3} — квантификатор, показывающий, что мы ищем три последовательно идущих символа из указанного набора.

В длинных словах найдено несколько совпадений с заданным шаблоном.

Поиск сочетаний из трех букв и/или цифр, идущих отдельным «блоком» — \b\w{3}\b

  • \w{3} — как мы знаем из предыдущего примера, это три любые буквы и/или цифры, идущие последовательно.
  • \b — указывает на начало и конец слова (см. шпаргалку внизу статьи).

Обратите внимание, что благодаря \b в выборку не попали длинные слова.

Отдельные слова, состоящие из трех букв — \b\[a-z]{3}\b

  • [a-z]{3} — любые три буквы.
  • \b — указывает на начало и конец слова.

Два слова — [a-zA-Z]+\s[a-zA-Z]+

Это выглядит страшнее, чем есть на самом деле. Мы задаем шаблон «слово пробел слово».

  • [a-zA-Z]+ — слово (любая буква из заданного набора, одна или больше).
  • \s — пробел (см. шпаргалку внизу статьи).

Обратите внимание, что сейчас с шаблоном совпала только Северная Дакота (North Dakota): только это название подходит к шаблону «слово пробел слово».

Одно или два слова — [a-zA-Z]+(\s[a-zA-Z]+)?

Тоже выглядит пугающе, но фактически мы задаем шаблон «слово (пробел слово)?»

  • [a-zA-Z]+ — слово.
  • \s — пробел.
  • ( … )? — опциональность. Вопросительный знак — это квантификатор, показывающий, что идущий перед ним блок встречается ноль или один раз (т. е. этого блока может и не быть).

Обратите внимание, что теперь в выборку попала не только Северная Дакота (потому что второе слово опционально).

Символы подстановки

Все, что заключено в скобки (жадная подстановка) — \(.*\)

  • \( и \) — сами скобки. Обратный слэш используется для экранирования специальных символов. Благодаря ему они трактуются как обычные (см. шпаргалку внизу статьи).
  • .* — «жадная» подстановка (точка — любой символ, звездочка — «жадный» квантификатор, благодаря ему из текста выбирается максимально длинная строка).

В эту жадную подстановку попадает все, что находится до последней закрывающей скобки.

Все, что заключено в скобки (ленивая подстановка) — \(.*?\)

  • \( и \) — сами скобки.
  • .*? — ленивая подстановка (*? — ленивый квантификатор, благодаря которому мы выбираем минимальную совпадающую строку).
  • Эта ленивая подстановка совпадет со всем, что находится до первой попавшейся закрывающей скобки.

Строки, содержащие символ звездочки — ^.*\*.*$

  • ^ и $ указывают на начало и конец строки соответственно (задаются опционально).
  • .* — подстановка.
  • \* — экранированный символ звездочки.

Строки без символа звездочки — ^[^\*]+$

  • ^ и $ указывают на начало и конец строки.
  • [^ … ] — совпадает со всем, что не указано в этих квадратных скобках:
    • \* — символ звездочки (экранированный).
    • [^\*] — совпадает со всем, кроме символа звездочки.
  • + — квантификатор: одно и более повторение совпадения.

Все строки, содержащие символ «е» — ^.*[e].*$

  • ^ и $ указывают на начало и конец строки.
  • .* — подстановка.
  • [e] — буква «е».

Все строки, в которых не содержится символ «е» — ^[^e]+$

  • ^ и $ указывают на начало и конец строки.
  • [^ … ] — совпадает со всем, что не указано в этих квадратных скобках:
    • [^e] — совпадает со всем, кроме буквы «е».
  • + — квантификатор: одно и более повторение совпадения.

Выражение в скобках, начинающееся с указанных слов — \((Jan|Jul|Dec).*\)

  • \( и \) — сами скобки.
  • (Jan|Jul|Dec) — совпадает со словами Jan, Jul или Dec.
  • .* — подстановка.

Смешанные соответствия

Короткий формат даты в скобках — [a-z]{3}\s+[0-9]+

  • [a-z]{3} — ровно три буквы.
  • \s+ — один или больше пробелов.
  • [0-9]+ — одна или больше цифр.

Полная дата в скобках — [a-z]{3}\s+[0-9]+,\s[0-9]+

Выражение не так страшно, как кажется. По сути это «слово число, число».

  • [a-z]{3} — ровно три буквы.
  • \s+ — один или больше пробелов.
  • , — запятая.
  • [0-9]+ — одна или больше цифр.

Слова, в середине которых есть буква «m» — [a-z]+[m][a-z]+

  • [a-z]+ — одна или больше букв.
  • [m] — буква m.

Обратите внимание, что Michigan не попал в выборку. Это потому, что в этом слове буква m стоит в начале, а не в середине.

Слова, в которых есть буква «m» (вообще, в любом месте) — ([a-z]+)?[m]([a-z]+)?

Опять же, выглядит страшно, но по сути это «(слово)? m (слово)?».

  • ( … )? — указывает на опциональность:
    • [a-z]+ — слово.
    • ([a-z]+)? — слово является опциональным.
  • [m] — буква m.

Обратите внимание, что теперь и Michigan совпадает с заданным шаблоном.

Исключение совпадений

Давайте попробуем найти совпадения с шаблоном, но при этом исключить из найденного сам шаблон. Это называется lookaround. (Есть «просмотр вперед» — lookahead и «просмотр назад» — lookbehind. А lookaround — их комбинация).

Чтобы в этом разобраться, давайте сравним поиск слова в скобках включая и исключая сами скобки.

Слово в скобках (включая скобки) — \([a-z]+\)

  • \( и \) — сами скобки.
  • [a-z]+ — слово.

Слово в скобках (но взятое без скобок, только само слово) — (?<=\()[a-z]+(?=\))

  • [a-z]+ — слово.
  • (?<= … ) — блок символов должен начинаться с указанного шаблона, но этот шаблон не входит в результат:
    • \( — символ открывающей скобки,
    • (?<=\() — совпадение начинается от открывающей скобки, но сама скобка в него не входит.
  • (?= … ) — блок символов кончается указанным шаблоном, но этот шаблон исключается из результата:
    • \) — символ закрывающей скобки,
    • (?=\)) — с шаблоном совпадает все, вплоть до закрывающей скобки, которая в результат не входит.

Все, что в скобках (сами скобки исключаются) — (?<=\().*?(?=\))

  • (?<=\() — совпадает со всем, начиная от открывающей скобки (при этом не захватывая саму скобку).
  • .*? — ленивая подстановка.
  • (?=\)) — совпадает со всем, вплоть до закрывающей скобки (при этом не захватывая саму скобку).

Все, что взято в скобки в строках, где есть звездочка — (?<=\*.*\().*?(?=\))

  • (?<= … ) — начало шаблона, исключающееся из результата:
    • \* — символ звездочки,
    • .* — жадная подстановка,
    • \( — символ открывающей скобки,
    • (?<=\*.*\() — подстановка от звездочки до открывающей скобки (при этом не захватывается ни то, ни другое).
  • .*? — ленивая подстановка.
  • (?=)) — совпадает со всем, что стоит до закрывающей скобки (при этом сама скобка не захватывается).

Все, что идет перед звездочкой, не захватывая саму звездочку — ^.*(?=\*)

  • ^ — начало строки.
  • .* — жадная подстановка.
  • (?=\*) — совпадает со всем, что идет до звездочки, не включая саму звездочку.

Шпаргалка

  • . ^ $ * + ? ( ) [ { \ | — зарезервированные символы
  • Обратный слэш служит для экранирования:
  • (abc) это шаблон для abc (в группах регулярных выражений)
  • \(abc\) это шаблон для (abc) (т. е. со скобками)
  • [a-zA-Z] — буквы (регистр имеет значение)
  • [0-9] или \d — цифры
  • [a-c1-3#] — набор из символов a b c 1 2 3 #
  • .* — жадная подстановка, .*? — ленивая подстановка
  • ^ — начало строки, $ — конец строки
  • \s — пробел, \t — табуляция, \n — новая строка
  • \w — буквы и цифры, \W — не буквы и не цифры
  • \b граница слова, \B — не граница слова
  • + — один повтор и более
  • {3} — ровно три повтора
  • {1,3} — от одного до трех повторов
  • {3,} — больше трех повторов
  • [^ … ] совпадает со всеми символами, кроме указанных в квадратных скобках
  • (?<= … ) — совпадает с тем, что начинается с указанных в скобках символов, но сами символы в результат не входят (look behind)
  • (?= … ) — совпадает со всем, что оканчивается на символы, указанные в скобках, но сами символы в результат не входят (look ahead).

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here