Дисклеймер
Данная статья написана с уклоном на практическое применение регулярных выражений в проектах. Изначально написана для начинающих разработчиков в моей компании. Статья включает в себя примеры использования на JavaScript (TypeScript).
Введение
Регуля́рные выраже́ния (англ. regular expressions) — формальный язык, используемый в компьютерных программах, работающих с текстом, для поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании метасимволов (символов-джокеров, англ. wildcard characters). Для поиска используется строка-образец (англ. pattern, по-русски её часто называют «шаблоном», «маской»), состоящая из символов и метасимволов и задающая правило поиска. Для манипуляций с текстом дополнительно задаётся строка замены, которая также может содержать в себе специальные символы.
Например, на вход приходит дата рождения в формате ДД.ММ.ГГГГ. Вам надо передать ее дальше, но уже в формате ГГГГ-ММ-ДД. Как это сделать с помощью простого поиска? Вы же не знаете заранее, какая именно дата будет.
Примеры использования регулярных выражений:
Удалить все файлы, начинающиеся на test (чистим за собой тестовые данные)
Найти все даты в тесте
Удалить все ненужные строки из тестового файла (например: поток данных из b2b)
Сопоставить переводы в репозитории с переводами из CMS (https://www.npmjs.com/package/check-i18n)
Создать конвертер данных с валидацией входных данных в виде строки
Валидация телефона, почты, ФИО
Работа с регулярными выражениями
Написание регулярных выражений
По своей сути, регулярные выражения являются языком разметки, аналогично HTML. В любом случае потребуется использование справочников при работе с ними (и постепенное запоминание ввиду опыта и частоты использования). Как показал опыт, наиболее полезным справочником оказался сайт https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Regular_Expressions.
Статья в Википедии оказалась также полезной - https://ru.wikipedia.org/wiki/Регулярные_выражения - но стоит делать скидку на то, что Википедию могут редко или неверно редактировать любые люди и информация может быть не всегда достоверной (в то время как MDN является основным справочником для разработки frontend).
Для фронтенд-разработчиков рекомендуется к прочтению - https://learn.javascript.ru/regexp-methods.
И да, фактически, единственным способом изучить регулярные выражения является практика работы со справочником. На первом этапе будет условно-достаточно прочитать статью на MDN.
При написании или проверке валидаторов с использованием регулярных выражений нужно по максимуму покрыть регулярное выражение тестами во избежания проблем в будущем. Почему? Сейчас вы проверили его на онлайн редакторе с кейсами, а в будущем выражение могут изменить и не заметить проблемы. Ручные QA редко создают кейсы для проверки ввода определенных полей в больших количествах, т.к. это не оправдано по времязатратам. Автотестов на интерфейсы также может не быть на проекте.
Особенности написания RegExp в JS (TS)
Общее
При написании регулярных выражений в JS (TS) большого размера или сложности у разработчика чаще всего возникает необходимость повторения или переиспользования частей регулярного выражения в том же выражении. Логично будет работать с применением принципа DRY и создать переменную, в которую будет вынесен повторяющийся отрезок выражения. Также вынесение в отдельный отрезок будет способствовать улучшению читаемости и будущего редактирования.
Стоит обратить внимание на нюансы при работе с классом RegExp и встроенной в язык интерпретацией регулярных выражений посредством синтаксиса (оборачивание в слеш):
лучшей практикой при работе с регулярными выражениями из своего опыта считаю создание регулярных выражений через класс RegExp
нельзя нормально конкатенировать две сущности класса RegExp, т.к. во время создания RegExp задается практически неизменяемый паттерн в конструкторе
для конкатенация двух отдельных регулярных выражений необходимо заранее архитектурно проработать входящие данные в сущность RegExp (т.е. заранее работать со строкой)
-
при работе со строками нужно учитывать использование специальных значений для регулярных выражений, т.е. особенности работы с обратными слешами, точками и др.
при использовании кавычек внутри строки необходима изоляция значения внутри строки для символа кавычек (см. пример переменной QUOTES_REGEXP_STR)
строка "съест" обратный слеш при создании строки, необходимо дублирование знака обратного слеша для прокидывания в регулярное выражение
еще раз напоминаю про точки (символ аналогичный любому знаку в регулярном выражении), их необходимо изолировать
Пример использования на реальном проекте:
|
Возможные проблемы
"Запоминание" положения поиска при работе с классом RegExp с флагом g
При работе с регулярным выражением через класс RegExp с флагом g
, используя методы .exec('') или .test('') происходит модификация свойства lastIndex. Сами же методы .exec('') и .test('') начинают проверку с позиции lastIndex.
Больше информации тут - https://learn.javascript.ru/regexp-methods#regexp-exec-str
Валидация написанных выражений
Для работы с регулярными выражениями крайне удобно использовать онлайн сервисы:
Если есть необходимость абстрагирования от онлайна, то можно использовать встроенные возможности текстовых редакторов или IDE, например:
Notepad++ (установить Search Mode → Regular expression)
Поиск в IDE Jetbrains (например: Webstorm) с указанием использования регулярного выражения (справа строки поиска значок "[.*]")
FAQ
Почему регулярное выражение указано обернутым в символах слеша?
При написании регулярных выражений в языках программирования есть различный синтаксис создания регулярных выражений как объекта. Например, в JS (TS) для создания объекта регулярного выражения можно использовать два способа: создание через конструктор класса ("new RegExp") или через синтаксис регулярного выражения через оборачивание прямыми слешами ("/выражение/"). Иногда данный синтаксис может встречаться в сопутствующих текстах. В данных случаях выражение без прямых слешей является синонимичным выражению без слешей.
Ссылки
Комментарии (1)
x4erem6a
20.04.2023 06:13Чтобы строка не съедала обратные слеши можно использовать
String.raw
:const pattern = String.raw`\d+`
x4erem6a
Чтобы строка не съедала обратные слеши можно использовать
String.raw
: