В работе и повседневной жизни мы буквально окружены текстами: книги и статьи, письма и чаты, веб-страницы и программный код. Да что там — сама биологическая жизнь основана на ДНК. И для эффективной работы по поиску или модификации текста уже давно был придуман мощный инструмент — регулярные выражения, или 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, помимо справочников и учебников в интернете, на Хабре можно почитать следующие статьи:
- Квантификаторы в регулярных выражениях
- 8 полезных регэкспов с наглядным разбором
- Некоторые ошибки при написании регэкспов
Сегодня я уже не представляю свою работу без регулярных выражений, как и без слепого метода печати. А требовалось всего лишь начать использовать. Чего вам и желаю.