Перевод статьи «Powerful regex for the practical dev».
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).
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]