Перейти к содержимому
Войти Регистрация

Топ 7 вещей, которые нужно знать про регулярные выражения

Топ 7 вещей, которые нужно знать про регулярные выражения

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

Зачем это нужно и где встречается

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

Где вы с ними столкнётесь. Поиск и замена в редакторе, фильтрация логов, проверка введённых данных, разбор выгрузок, настройки почти любого инструмента разработчика. В подборке про команды терминала grep стоит на втором месте — и без шаблонов он теряет половину смысла.

Хорошая новость. В реальной работе используется небольшая часть возможностей: символьные классы, квантификаторы, якоря и группы. Плохая новость — регулярки легко пишутся и тяжело читаются, в том числе собственные, месячной давности. Поэтому половина материала ниже не про синтаксис, а про то, как не создать проблему себе и коллегам.

Регулярка пишется за минуту, а читается через полгода — если о ней позаботились.
Регулярка пишется за минуту, а читается через полгода — если о ней позаботились. Фото: ajmexico · BY.

Топ 7 вещей, которые нужно знать

Символьные классы — кирпичи, из которых всё строится

половина работы делается пятью обозначениями

Обычные буквы в шаблоне означают сами себя: шаблон кот найдёт слово «кот». Интереснее становится, когда нужно описать не конкретный символ, а его вид.

Основные обозначения. \d — любая цифра, \w — буква, цифра или подчёркивание, \s — пробельный символ, точка — вообще любой символ, кроме перевода строки. Заглавные варианты означают отрицание: \D — всё, что не цифра.

Свои наборы. В квадратных скобках перечисляется допустимое: [абв] — одна из трёх букв, [а-я] — любая строчная кириллическая. Крышка внутри скобок означает «кроме»: [^0-9] — любой символ, кроме цифры.

Пример целиком. \d{3}-\d{2} — три цифры, дефис, две цифры. Такой шаблон найдёт «123-45» и не найдёт «12-345».

  • Пять обозначений закрывают большинство задач
  • Читаются интуитивно после первого объяснения
  • Одинаковы почти во всех языках
  • Точка внутри квадратных скобок означает просто точку, и это путает
  • Смысл \w и \d зависит от настроек Юникода

основа · оценка 9,5

Квантификаторы и жадность

главный источник ошибок у новичков

Квантификатор говорит, сколько раз повторяется предыдущий элемент. * — ноль или больше, + — один или больше, ? — ноль или один, {2,5} — от двух до пяти раз.

Ловушка жадности. По умолчанию квантификаторы захватывают максимум возможного. Классический пример: в строке с двумя парами кавычек шаблон «кавычка, любые символы, кавычка» захватит не первую пару, а всё от первой кавычки до последней — вместе с текстом между парами. Это почти никогда не то, что вам нужно.

Лечится знаком вопроса. Добавленный после квантификатора, он делает его ленивым: .+? берёт минимум символов, а не максимум. Второй способ надёжнее: вместо «любых символов» описать, чего там быть не должно, — например, «любой символ, кроме кавычки».

Правило. Увидели в шаблоне точку со звёздочкой — проверьте, не захватит ли она лишнего. Обычно захватывает.

  • Позволяют описывать переменную длину
  • Ленивый вариант включается одним символом
  • Диапазон повторений задаётся точно
  • Жадность по умолчанию неочевидна и молча портит результат
  • Вложенные квантификаторы способны обрушить производительность

частая ошибка · оценка 9,4

Якоря и границы слов

разница между «содержит» и «равно»

По умолчанию регулярка ищет совпадение в любом месте строки. Проверка «состоит ли строка только из цифр» шаблоном \d+ вернёт истину и для строки «абв123» — потому что цифры там есть.

Якоря. ^ — начало строки, $ — конец. Шаблон ^\d+$ уже означает «вся строка целиком состоит из цифр». Это самая частая причина, по которой проверка данных работает не так, как задумано.

Граница слова. \b отмечает переход между буквенным и небуквенным символом. Шаблон кот найдёт «кот» внутри слова «который», а \bкот\b — только отдельное слово. При замене по всему проекту это спасает от катастрофы.

Про многострочность. В соответствующем режиме якоря означают начало и конец каждой строки, а не всего текста, — этот флаг стоит проверять, когда шаблон ведёт себя странно.

  • Превращают поиск в строгую проверку
  • Граница слова спасает при массовой замене
  • Записываются одним символом
  • Поведение якорей меняется от флага многострочности
  • Про них забывают чаще всего

проверка данных · оценка 9,3

Группы, захват и замена

то, ради чего регулярки чаще всего и берут

Круглые скобки делают две вещи: объединяют часть шаблона в единое целое и запоминают то, что в неё попало. Запомненное потом доступно по номеру — в коде или прямо в строке замены.

Пример с датой. Шаблон (\d{4})-(\d{2})-(\d{2}) разбирает дату на три части, а строка замены $3.$2.$1 переставляет их в привычный вид. В части инструментов та же запись выглядит как \3.\2.\1.

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

Незахватывающие группы. Если скобки нужны только для группировки, содержимое можно не запоминать — тогда нумерация остальных групп не съезжает.

Выбор из вариантов. Вертикальная черта означает «или»: (январь|февраль|март). Скобки обязательны, иначе выбор распространится на весь шаблон.

  • Позволяют не только найти, но и разобрать строку на части
  • Замена с перестановкой делается в одну операцию
  • Именованные группы читаются через полгода
  • Нумерация групп съезжает при правках шаблона
  • Синтаксис именованных групп отличается между языками
  • Вложенные группы быстро становятся нечитаемыми

разбор строк · оценка 9,2

Где не надо и как остаться читаемым

самая полезная часть, которую пропускают

Не разбирайте регулярками HTML. Это не вкусовщина: разметка допускает вложенность произвольной глубины, комментарии, атрибуты в кавычках и без, а регулярные выражения по своей природе не умеют работать с вложенностью. Шаблон, который «работает» на трёх страницах, сломается на четвёртой, причём молча. Для разметки существуют парсеры, они есть в каждом языке и стоят одной строки подключения.

То же касается JSON, XML и CSV. Запятые внутри кавычек и вложенные объекты регулярка обрабатывать не обязана, а библиотека делает это по умолчанию.

Длинное выражение без комментария нечитаемо. Строку из шестидесяти символов со скобками и слэшами через полгода не прочитает никто, включая её автора. Минимум, который стоит делать всегда: над регуляркой строчка обычным языком — что она должна поймать, и один пример подходящей строки и один пример неподходящей.

Как сделать лучше. Многие языки поддерживают режим с пробелами и комментариями внутри шаблона — тогда выражение записывается в несколько строк с пояснениями. Второй приём: собрать сложный шаблон из коротких кусков с осмысленными именами. Тот же подход, что и в остальных правилах читаемого кода.

  • Избавляет от целого класса неуловимых ошибок
  • Комментарий и два примера стоят одной минуты
  • Разбиение на части упрощает отладку
  • Режим с комментариями поддерживают не все языки
  • Соблазн написать «одной строчкой» очень силён

про поддержку кода · оценка 9,1

Диалекты и экранирование

почему шаблон из интернета не работает у вас

Единого стандарта нет. Синтаксис в JavaScript, Python, Java, PHP и в утилитах вроде grep и sed отличается в деталях: именованные группы, просмотр вперёд и назад, поддержка Юникода, флаги — всё это записывается по-разному.

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

Двойное экранирование. В большинстве языков регулярка записывается обычной строкой, а обратный слэш в строках имеет собственный смысл. Отсюда шаблоны с удвоенными слэшами и постоянная путаница. Лечится специальным видом строковых литералов, который есть почти везде: в нём слэш означает сам себя.

Про Юникод. Обозначение \w в разных движках и настройках то включает кириллицу, то нет. Если работаете с русским текстом, проверьте это первым делом — иначе шаблон будет отлично работать на латинице и молча пропускать половину данных.

  • Базовый синтаксис всё же общий для всех
  • Различия документированы и легко проверяются
  • Песочницы позволяют выбрать диалект и проверить сразу
  • Готовый шаблон из интернета редко работает как есть
  • Двойное экранирование делает выражение вдвое менее читаемым
  • Поведение с кириллицей зависит от настроек

переносимость · оценка 9,0

Производительность и катастрофический возврат

редкая проблема с очень дорогими последствиями

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

Как это выглядит на практике. На коротких строках всё быстро, на строке в несколько десятков символов — секунды, на строке чуть длиннее — минуты. Если такой шаблон применяется к данным, которые присылает пользователь, получается способ уронить сервис одним запросом.

Что делать. Избегать вложенных квантификаторов, не описывать «что угодно» там, где можно перечислить допустимые символы, ограничивать длину входных данных до проверки. В языках, где есть таймаут на выполнение регулярки, его стоит выставлять для всего, что приходит извне.

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

  • Проблема хорошо изучена, признаки известны
  • Есть анализаторы, которые находят опасные шаблоны
  • Ограничение длины ввода снимает большую часть риска
  • Обнаруживается обычно уже на боевом сервере
  • Опасный шаблон внешне не отличается от безопасного

безопасность · оценка 8,8

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

Короткая шпаргалка

ЗадачаШаблонЧто важно
Только цифры, вся строка^\d+$без якорей поймает цифры внутри любого текста
Отдельное слово\bслово\bиначе найдётся внутри других слов
Текст в кавычках"[^"]*"надёжнее, чем точка со звёздочкой
Дата из трёх частей(\d{4})-(\d{2})-(\d{2})группы доступны в замене по номерам
Один из вариантов(да|нет|возможно)скобки обязательны
Необязательный кусокцвета?вопрос относится только к предыдущему символу
Диаграмма оценок семи тем о регулярных выражениях
Оценка — по тому, насколько тема нужна в реальной работе, а не по её сложности.

Как писать регулярку, чтобы потом не страдать

Начните с примеров, а не с шаблона. Выпишите пять строк, которые должны совпасть, и пять, которые совпасть не должны. Вторая половина списка важнее: именно на ней ломаются шаблоны, которые «вроде работают».

Проверяйте в песочнице. Онлайн-инструменты показывают, какая часть шаблона что захватила, и объясняют каждый символ, — это быстрее, чем гадать.

Оставьте след для будущих читателей. Строка комментария и два примера — подходящий и неподходящий. Через полгода это сэкономит коллеге вечер.

Закройте тестом. Регулярка — идеальный кандидат на короткий тест: набор строк и ожидаемый результат. Пишется за пять минут и ловит правки, которые «просто чуть-чуть поправили шаблон».

Частые вопросы

С чего начать, если раньше не пользовался?

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

Можно ли проверять адрес почты регулярным выражением?

Полностью по стандарту — нет: корректное выражение получается чудовищным и всё равно пропускает крайние случаи. Практичный подход — минимальная проверка на символ собаки и точку после него, а настоящая проверка делается письмом с кодом. С телефонами так же: строгий шаблон отсекает живых пользователей чаще, чем ошибки.

Почему шаблон работает в редакторе, но не работает в терминале?

Разные диалекты: в базовом режиме grep часть символов нужно экранировать, а расширенный режим включается отдельным ключом. Плюс оболочка съедает часть символов по дороге — поэтому шаблон в командной строке берут в одинарные кавычки.

Стоит ли просить нейросеть написать регулярку?

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

Итог

Выучите четыре вещи — символьные классы, квантификаторы с их жадностью, якоря и группы. Этого набора хватает на подавляющее большинство реальных задач, а остальное ищется точечно, когда понадобится.

И держите в голове два ограничения. Разметку и структурированные форматы разбирают парсерами, а не шаблонами. А выражение длиннее строки требует комментария и пары примеров рядом — иначе через полгода его проще выбросить и написать заново.

0
Оценили 0 читателей

Комментарии

0
Г
Без регистрации можно оставить один комментарий к публикации. Войдите, чтобы участвовать в обсуждении дальше и получать ответы. Ссылки в комментариях скрываются.
Пока нет комментариев

Будьте первым, кто ответит автору.