Источник: Nuances of Programming
Регулярные выражения (regex или regexp) очень эффективны для извлечения информации из текста. Для этого нужно произвести поиск одного или нескольких совпадений по определённому шаблону (т. е. определённой последовательности символов ASCII или unicode).
Области применения regex разнообразны, от валидации до парсинга/замены строк, передачи данных в другие форматы и Web Scraping’а.
Одна из любопытных особенностей регулярных выражений в их универсальности, стоит вам выучить синтаксис, и вы сможете применять их в любом (почти) языке программирования (JavaScript, Java, VB, C #, C / C++, Python, Perl, Ruby, Delphi, R, Tcl, и многих других). Небольшие отличия касаются только наиболее продвинутых функций и версий синтаксиса, поддерживаемых движком.
Давайте начнём с нескольких примеров.
Основы
Квантификаторы — * + ? и {}
Оператор ИЛИ — | или []
Символьные классы — \d \w \s и .
Флаги
Мы научились строить регулярные выражения, но забыли о фундаментальной концепции ― флагах.
Регулярное выражение, как правило, записывается в такой форме /abc/, где шаблон для сопоставления выделен двумя слешами /. В конце выражения, мы определяем значение флага (эти значения можно комбинировать):
- g (global) ― не возвращает результат после первого совпадения, а продолжает поиск с конца предыдущего совпадения.
- m (multi line) ― с таким флагом, операторы ^ и $ вызовут совпадение в начале и конце строки ввода (line), вместо строки целиком (string).
- i (insensitive) ― делает выражение регистронезависимым (например, /aBc/i соответствует AbC).
Средний уровень
Скобочные группы ― ()
Этот оператор очень полезен, когда нужно извлечь информацию из строк или данных, используя ваш любимый язык программирования. Любые множественные совпадения, по нескольким группам, будут представлены в виде классического массива: доступ к их значениям можно получить с помощью индекса из результатов сопоставления.
Если присвоить группам имена (используя (?<foo>...)), то можно получить их значения, используя результат сопоставления, как словарь, где ключами будут имена каждой группы.
Скобочные выражения ― []
Помните, что внутри скобочных выражений все специальные символы (включая обратную косую черту \) теряют своё служебное значение, поэтому нам ненужно их экранировать.
Жадные и ленивые сопоставления
Квантификаторы ( * + {}) ― это «жадные» операторы, потому что они продолжают поиск соответствий, как можно глубже ― через весь текст.
Например, выражение <.+> соответствует <div>simple div</div> в This is a <div> simple div</div> test. Чтобы найти только тэг div ― можно использовать оператор ?, сделав выражение «ленивым»:
<.+?> соответствует любому символу, один или несколько раз найденному между < и >, расширяется по мере необходимости
-> тест
Обратите внимание, что хорошей практикой считается не использовать оператор . , в пользу более строгого выражения:
<[^<>]+> соответствует любому символу, кроме < или >, один или более раз встречающемуся между < и >
-> тест
Продвинутый уровень
Границы слов ― \b и \B
\babc\b выполняет поиск слова целиком
-> тест
\b ― соответствует границе слова, наподобие якоря (он похож на $ и ^), где предыдущий символ ― словесный (например, \w), а следующий ― нет, либо наоборот, (например, это может быть начало строки или пробел).
\B ― соответствует несловообразующей границе. Соответствие не должно обнаруживаться на границе \b .
\Babc\B соответствует, только если шаблон полностью окружён словами
-> тест
Обратные ссылки — \1
([abc])\1 \1 соответствует тексту из первой захватываемой группы
-> тест
([abc])([de])\2\1 можно использовать \2 (\3, \4, и т.д.) для определения порядкового номера захватываемой группы
-> тест
(?<foo>[abc])\k<foo> мы присвоили имя foo группе, и теперь ссылаемся на неё используя ― (\k<foo>). Результат, как и в первом выражении
-> тест
Опережающие и ретроспективные проверки — (?=) and (?<=)
d(?=r) соответствует d, только если после этого следует r, но r не будет входить в соответствие выражения
-> тест
(?<=r)d соответствует d, только если перед этим есть r, но r не будет входить в соответствие выражения
-> тест
Вы можете использовать оператор отрицания !
d(?!r) соответствует d, только если после этого нет r, но r не будет входить в соответствие выражения
-> тест
(?<!r)d соответствует d, только если перед этим нет r, но r не будет входить в соответствие выражения
-> тест
Заключение
Как вы могли убедиться, области применения регулярных выражений разнообразны. Я уверен, что вы сталкивались с похожими задачами в своей работе (хотя бы с одной из них), например такими:
- Валидация данных (например, правильно ли заполнена строка time)
- Сбор данных (особенно веб-скрапинг, поиск страниц, содержащих определённый набор слов в определённом порядке)
- Обработка данных (преобразование сырых данных в нужный формат)
- Парсинг (например, достать все GET параметры из URL или текст внутри скобок)
- Замена строк (даже во время написания кода в IDE, можно, например преобразовать Java или C# класс в соответствующий JSON объект, заменить “;” на “,”, изменить размер букв, избегать объявление типа и т.д.)
- Подсветка синтаксиса, переименование файла, анализ пакетов и многие другие задачи, где нужно работать со строками (где данные не должны быть текстовыми).
Читайте нас в телеграмме и vk
Перевод статьи Jonny Fox: Regex tutorial — A quick cheatsheet by examples