В работе и повседневной жизни мы буквально окружены текстами: книги и статьи, письма и чаты, веб-страницы и программный код. Да что там — сама биологическая жизнь основана на ДНК. И для эффективной работы по поиску или модификации текста уже давно был придуман мощный инструмент — регулярные выражения, или regex. Однако по ряду причин далеко не все их используют, или имеют дело с ними только когда заставили при крайней необходимости. В этой статье я попытаюсь исправить эту печальную ситуацию.



Чтобы функции отыскать, воедино созвать и единою чёрною волей сковать.

На Хабре уже есть ряд хороших статей, которые помогут разобраться в основах:


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


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


^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$&^()*])[a-zA-Zа-яА-Я0-9!@#$&^()*]{1,}$

после чего настроение неизменно падает. Даже если и удалось продраться через нагромождение символов, то желание возвращаться к регулярным выражениям наверняка сильно уменьшится. Человек же со стороны вообще может принять это за инопланетный язык и начать сторониться аки чумы: «Зачем мне ещё один язык программирования, да к тому же такой сложный?».



Гэндальф ещё Серый, а потому боится использовать regex.

Поиск


Для экспериментов нам понадобится старый добрый Властелин Колец и любой текстовый редактор с поддержкой регулярных выражений. В данной статье будет использоваться Notepad++ (простой, удобный и расширяемый – очень рекомендую).
Копируем текст без оглавления в приложение, Ctrl+f, отмечаем «Regular expression» и вперёд!



Пример окна поиска в Notepad++.

1. Точное совпадение с фразой


Попробуем найти Исилдура (того, что у Саурона кольцо подрезал) на страницах «Властелина колец»




Поздравляю! Вы только что использовали регулярное выражение «Исилдур».
Тут всё просто – совпадение один к одному. Есть еще магия регистров букв (отмечаем галочку «Matсh Case»), но по умолчанию она обычно не включена. «Исилдур», «исилдур», «ИсИлДУР» дадут один и тот же результат. Если же мы знаем регистры букв искомого слова, то можем указать их и отбросить лишние результаты. Однако это может сыграть злую шутку, когда при последующем поиске может потеряться часть результатов. Убирайте галочку, если регистры букв могут быть разными.


Веб браузеры, текстовые редакторы, мессенджеры – все имеют такую функцию. Однако не все об этом знают. Жаль, что у бумажных книг нет такой возможности.


Первый шаг сделан, и ничего не мешает двигаться дальше.



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


Еще одна распространённая возможность — это символ подстановки (wildcard) звёздочка «*». Она заменяет любое количество любых допустимых символов. Самый распространённый пример – поиск файлов.


Скажем, мы хотим найти фотографии отдыха на море. Для этого в строке поиска введём «*.png» – и получим список всех фотографий в папке:



Скан паспорта.png
Море Испания.png
Тосса-де-Мар, море.png
Трудовые будни.png
Закатное море, Сант-Себастиа.png

Уже хорошо. А что будет, если мы добавим слово «море» до или после звездочки?
море*.png

Море Испания.png

*море.png

Тосса-де-Мар, море.png

Следующий вариант вернёт то, что нужно:
*море*.png

Море Испания.png
Тосса-де-Мар, море.png
Закатное море, Сант-Себастиа.png

«*море*.png» — наглядный пример шаблона поиска, или маски – мы что-то знаем о структуре искомой строчки (в данном случае расширение «.png» в конце и где-то слово «море»), в остальных местах предполагаем любые символы.


Регулярные выражения, как развитие подстановочных символов, имеют в своём арсенале огромный набор разнообразных средств, с помощью которых мы можем более тонко составлять шаблон поиска. Но пока познакомимся с аналогом звёздочки — точка и звёздочка «.*».



3. Точка со звёздочкой «.*»


Забудем о значении звёздочки в подстановочных символах – в регулярных выражениях она обозначает «любое количество, от 0 и до бесконечности». А точка обозначает «любой строковый символ». Вместе получаем «любое количество любых строковых символов».


Точка не включает в себя символ новой строки, поэтому поиск будет производится до конца строки, или, другими словами, абзаца. Посмотрим, как часто Фродо и Сэм оказывались вместе: для этого поищем по шаблонам «Сэм.*Фродо» и «Фродо.*Сэм»»:




215 совпадений. Кто бы сомневался…




Можно это сделать проще, одним запросом. Для этого используем специальный знак ИЛИ «|»: альтернативные варианты разделяются вертикальной чертой и окружаются скобками:
(Фродо.*Сэм|Сэм.*Фродо)




Можно заметить, что такой поиск выдал меньше совпадений — 213. Так получается, потому что, например, строчку «Рядом с Фродо шел всхлипывающий Сэм, да и сам Фродо безмолвно плакал.» раздельные запросы найдут два раза.


Чтобы узнать, как часто упоминается Гэндальф в полной форме, используем шаблон:
Гэндальф (Серый|Белый)




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


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



Саруман понимает, какая мощь в его руках, и не боится её. Поэтому он всегда в курсе всех дел.

4. Количество повторений или квантификаторы


С одним квантификатором мы уже познакомились – звёздочка. Есть ещё несколько способов задать количество:
{4} точное количество
{1,5} диапазон
{2,} от числа до бесконечности
{,7} от 0 до числа

Некоторые часто используемые диапазоны имеют собственные символы:
* или {0,} любое количество
? или {0,1} ноль или один
+ или {1,} есть как минимум один

Спросим, как часто упоминается одно и то же слово в одном абзаце:




Бильбо 2 раза — «(Бильбо.*){2}» — упоминается в 7 случаях, а большее количество раз в абзаце — «(Бильбо.*){3,}» — ни разу. Слово «Хоббит» встречается аж 3 раза в строке, как часть слов «Хоббиты» «хоббита» и «Хоббитании».



5. Представление символов


Точка (любой символ) — один из примеров представления символов. Другими примерами являются цифра «\d», цифра или буква «\w», набор символов «[abc], «[1-9], «[.,?:;]».
Например, мы хотим узнать, как часто числа используются в книге:
«\d+» или «\d{1,}» – как минимум одна цифра подряд:




Находим номера глав и даты. Если не брать совсем уж легендарные времена (37г.), то рассказ ведётся о втором тысячелетии по летоисчислению хоббитов (Л. Х.) Оценим масштаб саги, для этого найдём 4 цифры подряд — \d{4}




Первая дата говорит нам о начале табаководства у хоббитов в 1070 году, а Фродо уплывает от нас на Запад в 1421 — 351 год.


С остальными представлениями символов предлагаю познакомиться самостоятельно.



Замена




Как только фамилию Бильбо не переводили: Сумникс, Беббинс, в нашем случае – Торбинс, но для меня есть только один вариант — Бэггинс. Однако это не проблема: почти всегда рядом с возможностью поиска есть возможность замены. Найденное слово можно заменить по всему тексту в одно действие. Для этого воспользуемся вкладкой «Replace»:




Теперь можно читать книгу с привычным переводом. Но будьте осторожны: шаблон поиска может подойти не только желаемому слову, но и более длинному, содержащему в себе искомое. Тогда при замене «дача» на «деревня» мы неожиданно можем получить «удеревня» или «телепередеревня». Желательно предварительно провести поиск по такому же шаблону и проверить результаты. Усложняйте шаблон для более точного поиска. В случае «дача» мы можем добавить пробел до слова и пробел или знаки препинания в конце: « дача[ .,!?;:]».

Практика использования


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



Кольцо находит все определения функций в ISO C99, и потому такое могущественное.

В строке сверху мы вводим регулярное выражение, а снизу — текст, по которому производим поиск. Редактор автоматически подсвечивает найденные совпадения, при наведении на части выражения всплывают подсказки, объясняющие значение, и много других полезных функций. Для замены нужно выбрать «Substitution» в левой панели.

Заключение


  • Чаще пользуйтесь поиском для удобства и ускорения работы.
  • Используйте звёздочку при поиске файлов, создавая простые шаблоны.
  • Начните использовать простые регулярные выражения в повседневной работе, накапливая опыт и постепенно изучая новые возможности.

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


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