Comments 55
Пойду попью ромашкового чаю.
(Автор|Дани{2}л)(\s*,\s*|\s+)пиши ещё!*
Главная проблема регулярок для меня - изучать их в отрыве от конкретной задачи ленишься, а при решении конкретной задачи они эмбеддеру нужны раз в год. Поэтому каждый раз открываешь их для себя с нуля :)
За мануал спасибо, было наглядно. Увижусь с ним, по моим расчетам, месяца через четыре :)
Ну, прямо ембедить наверно редко надо, но наверняка возникают задачи, связанные с процессом разработки: логи распарсить, найти и заменить что-то в коде и т.д. В конечном итоге время, потраченное на изучение, окупается.
Разработчики делятся на два типа: тех, кто уже понимает регулярные выражения
А разработчики, которые используют регулярные выражения, делятся на тех, кто уже решал проблемы с их производительностью, и тех, кто ещё нет ;)
hello *,? *world
оно
Да, производительность — это отдельная тема )
Я бы сказал больная тема....
Если набить руку, это довольно быстро перестает быть больной темой. Увидеть фрагменты выражения, в которых движок свалится в лишний backtracking, несложно.
Навскидку назову такие способы увеличить производительность:
использовать максимально точные символьные классы
заменить квантификаторы на lazy везде, где не нужна жадность
расставить якоря и границы везде, где их можно расставить
В качестве заключающего штриха еще можно убрать сохраняющие скобки везде, где группу не надо сохранять: мелочь, но тоже помогает производительности.
Классический пример: в регэкспе ".+"
достаточно понять, что внутри кавычек нам нужен не любой символ, а любой-кроме-кавычки-символ, чтобы сделать вот так: "[^"]+"
и сразу избавиться от ужасного бэктрекинга.
и с ReDoS
Жду продолжения! Пока, вроде, понял... :-)
Вообще регулярных выражений существует больше одного стандарта: https://ru.wikipedia.org/wiki/Регулярные_выражения#Разновидности_регулярных_выражений
И про регулярки раз сто на хабре писали: https://habr.com/ru/search/?target_type=posts&order=relevance&q=[regexp]
Главная цель и отличительная черта этой серии статей — максимальная простота. Нюансов очень много, и если бросать их на читателя все разом, получится просто перегруз информацией.
В том числе и про различные "наречия" планировал упомянуть в следующей главе. Без конкретных примеров, чем именно отличаются, просто как сам факт.
Угу - писать про регулярки, не уточняя диалект, всё равно что играть в преферанс, не договорившись о системе.
Я признаю мощность и красоту регулярок, но вместе с тем есть и пару проблем:
- Они очень информационно плотные, их тяжело читать и разбирать, получается writeonly подход.
- Мне они нужны довольно редко, в лучшем случае раз в пару месяцев. Соответственно каждый раз приходится гуглить, особенно если задача нетипичная. Python, С# и прочие Java имеют какие то маленькие нюансики в синтаксисе стандартного средства регулярок, поэтому без гуглежа можно не понять, что конкретно не завелось.
А так хорошая штука конечно.
Для слабых духом есть библиотеки, собирающие регулярки из человекочитаемых конструкций наподобие LINQ, к примеру вот такая:
https://github.com/ricoapon/readable-regex
Спасибо за ссылку на библиотеку!
Тоже когда-то задумывался о создании чего-то подобного, чтобы вместо иероглифов были простые человеческие конструкции. Однако, когда натолкнулся на regexper, понял, что графический язык лучше помогает читать регулярки, чем даже самый многословный текст. По крайней мере, для меня так.
их тяжело читать и разбирать, получается writeonly подход.
О да, регулярки - такая штука, где можно забыть про "Чистый код" и с чистой совестью нафигачить огромный нечитаемый однострочник. Но не столько из-за недостатков регулярок, сколько из-за того, что это не осуждается, все так делают.
В диалектах без extended-режима (?x)
(например, в JS его нет) регулярку можно собирать по частям - из переменных с говорящими именами.
А если режим есть, то становятся доступны комментарии, форматирование пробелами и переносами строк.
(?x) # some comment
\d+ # some comment
\ # match single space
\d+ # some comment
ИМХО, самое страшное в регулярках то, что в разном софте слегка разный синтаксис. grep, sed, nginx, apache, php, javascript... Маски и "полноценные regex", PCRE и POSIX...
Вот и получается, что, кажется, знаешь общие принципы, подстановки... Но всё-равно приходится гуглить, например, как конкретно в этом случае организовать именованную группу, как отключить "жадный" режим" и т.п.
В прошлом году сдавал ЕГЭ по информатике (чтобы поступить в вуз), где-то 4 или 5 задач решил одной строчкой регекса, потратив на каждую пару минут.
В реальной разработке, если вижу регулярку, там где можно обойтись парой-тройкой ифчиков, то мне хочется убивать. Как правило регулярки сильно ухудшают читаемость кода, и крайне плохо модифицируются кем либо, кроме автора регулярки. Поэтому, если можно не писать регулярку, то ни в коем случае ее писать не следует
Имхо, регулярки в первую очередь полезны не как вставки в продакшн коде, а для ситуативных задач вроде поиска/замены в коде/логах, ну и для скриптов, которые читать будет только автор.
У регулярных выражений есть огромный плюс - они могут быть параметром, который выводится в настройки.
И мне, например, наоборот не нравится, когда потенциально изменяющуюся логику жёстко прописывают ифчиками или городят стратегии и фабрики валидаторов, вместо регулярки. Естественно, при условии, что использование регулярных выражений не спровоцирует кризис производительности. А то с другой стороны мне доводилось видеть, как регулярки использовали для добывания значений параметров из файла, каждый раз скармливая весь файл для каждого искомого параметра )
Главное не переборщить, а то получится что-то типа конфигов sendmail .
Недумал я, что блоксхемы могут быть даже тут. С блоксхемами на много понятнее. Спасибо. Очень интересно.
Для меня регулярки бывают двух видов - распространённые (валидация email, телефона, адреса и т.д.), и локальные - массово что-то в проекте заменить.
Вторые пишутся обычно за 2 минуты по шпаргалке, а первые лучше всего взять с гитхаба или СО.
P.S. Если вы используете сложную регулярку, и ее нельзя заменить - оберните ее хотя бы в читаемый вид - или в переменную типа phoneValidationRegExp, или в функцию с читаемым названием. Иначе потом будет больно.
валидация email
Всегда вспоминается это, когда-то кто говорит про валидацию email в контексте регулярных выражений. :)
https://pdw.ex-parrot.com/Mail-RFC822-Address.html
Регулярные выражения - это типичный write only код, отлично подходит для одноразовых скриптов, но в продакшен коде сложные регулярки - это почти всегда боль, особенно если их нужно поддерживать и дописывать/переписывать под новые требования. Без тулов, раскладывающих регулярки на понятные читаемые блоки, не обойтись.
Кстати, нет ли (проверенных в промышленных условиях) библиотек, оперирующих синтаксисом регулярных выражений в виде объектов? Что-нибудь типа one_or_more(one_of("abc"))+zero_or_more(whitespace)+...
Зачем? Зачем эти два с половиной листа в Ворде?
Разве валидный email это не: "строка не нулевой длины" + "собачка" + "строка не нулевой длины" + "точка" + "строка не нулевой длины" ?
Читайте мануал . Конкретно формат адреса расписывается в п.6, но остальные части тоже релевантны. Например, в e-mail адресе допускаются комментарии в определённом формате.
Ок, допустим "точек" может быть несколько, но это полностью подпадает под правило "строка не нулевой длины ". Зачем городить для этого что-то монструозное?
Не все строки ненулевой длины являются частью валидного e-mail.
[a-zA-Z0123456789._] устроит? (возможно еще пару символов забыл)
Хотя бы вот такое - jsmith@[IPv6:2001:db8::1] - обработайте для начала ) Да, произвольно употреблять скобки и двоеточия нельзя. Дальше перейдём к комментариям и явному роутингу (давно не используется, но по RFC822 возможен).
Ок, тогда вопрос в том, а обработает ли данных адрес почтовик того же Гугла, Эпла и тд? Обработает - это отправка и прием писем, без "отколупов" и попадания в папку "спам". Если нет - то вся обработка подобных адресов - бесполезна.
Лучшее, что читал про регулярные выражения. Точнее - лучшее изложение.
Это очень интересно, но вот ИМХО любую регулярку уже можно смело отдавать чатгпт и забыть про это.
Все равно если ты их не пишешь каждый день, ты их пишешь с гуглом и справочником. При этом практическая польза от скилла «умею читать/писать регулярки» сомнительная.
Умею читать от умею писать отличается ОЧЕНЬ сильно.
Мне они практически не нужны, использую ОЧЕНЬ редко, и, как мне кажется, для ситуативных случаев они хороши. Но вот разбираться с чужой (или старой своей, которой более полугода) - боль. Проще новую накидать.
И отдать её написать кому-то (той же нейронке) это равносильно тому, что разбираться в чужой (её же надо проверить). Спасибо, ни за какие деньги.
Сам автор курса по регуляркам, что могу сказать на последний комментарий, если в вашей работе нет задач в которых они нужны — вы просто мало и не глубоко работаете с текстом. Регулярки не панацея, но некоторые задачи позволяют решать в разы быстрее, чем то же самое описать обычными условиями. Сам ими пользуюсь везде, при написании кода, в терминальной строке, в корректуре приходящих извне объемных данных...
По сути статьи, лучше примеры брать более жизненные. И раз уж примеры синтетические, то не нужна очень большая точность совпадения, а потому: `hello[ ,]*world` вполне достаточно
hello,,,,,world
helloworld
hello , , , , ,world
Нормально для простого примера, аналогично !*, иначе получается где-то мы точно ищем, а где-то допускаем вольности. Иначе:
(h[ea]llo|привет|bonjour)(\s*,\s*|\s+)world!*
Лучше писать без вторых круглых скобок, нам не нужно сохраняющее состояние, не нужен вариант \s+, его покрывает \s* только нужно исключить запятую ,?
(h[ea]llo|привет|bonjour)\s*,?\s*world!*
Это чтобы не допустить вариант helloworld.
Да, я понимаю, что примеры надуманные и нереалистичные. Но для меня главное была простота и последовательность изложения. Любой реалистичный пример ломает последовательность.
при написании кода, в терминальной строке, в корректуре приходящих извне объемных данных...
Хорошие примеры, но всё это скорее разовые задачи, чем часть production кода - и подходы могут быть разные. Скажем, если надо быстренько посмотреть на какие-то паттерны в бинарном коде - наверное, пройдусь регулярками по выхлопу objdump -d. Если надо добавить такую фичу в продукт - скорее возьму для парсинга готовую библиотеку (скажем, из llvm), даже если на входе именно дизассемблированный текст.
Регулярки приятны тем, что не нужно уметь программировать, чтобы пользоваться sed/grep и обрабатывать массивы текста. Ну и поиск в Sublime, Libreoffice.
Был период, когда я мог писать регулярки, иногда довольно сложные, не заглядывая в доки и мануалы, а потом я перестал писать регулярки самостоятельно и начал даже иногда улыбаться!
Регулярные выражения простыми словами. Часть 1