Pull to refresh

Comments 55

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

За мануал спасибо, было наглядно. Увижусь с ним, по моим расчетам, месяца через четыре :)

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

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

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

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

hello *,? *world

оно



Да, производительность — это отдельная тема )

Я бы сказал больная тема....

Если набить руку, это довольно быстро перестает быть больной темой. Увидеть фрагменты выражения, в которых движок свалится в лишний backtracking, несложно.

Навскидку назову такие способы увеличить производительность:

  • использовать максимально точные символьные классы

  • заменить квантификаторы на lazy везде, где не нужна жадность

  • расставить якоря и границы везде, где их можно расставить

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

Классический пример: в регэкспе ".+" достаточно понять, что внутри кавычек нам нужен не любой символ, а любой-кроме-кавычки-символ, чтобы сделать вот так: "[^"]+" и сразу избавиться от ужасного бэктрекинга.

Жду продолжения! Пока, вроде, понял... :-)

Главная цель и отличительная черта этой серии статей — максимальная простота. Нюансов очень много, и если бросать их на читателя все разом, получится просто перегруз информацией.

В том числе и про различные "наречия" планировал упомянуть в следующей главе. Без конкретных примеров, чем именно отличаются, просто как сам факт.

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

Угу - писать про регулярки, не уточняя диалект, всё равно что играть в преферанс, не договорившись о системе.

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

Да какие advanced, периодически путаюсь, где какие скобки надо экранировать.

Я признаю мощность и красоту регулярок, но вместе с тем есть и пару проблем:
- Они очень информационно плотные, их тяжело читать и разбирать, получается 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 задач решил одной строчкой регекса, потратив на каждую пару минут.

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

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

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

И мне, например, наоборот не нравится, когда потенциально изменяющуюся логику жёстко прописывают ифчиками или городят стратегии и фабрики валидаторов, вместо регулярки. Естественно, при условии, что использование регулярных выражений не спровоцирует кризис производительности. А то с другой стороны мне доводилось видеть, как регулярки использовали для добывания значений параметров из файла, каждый раз скармливая весь файл для каждого искомого параметра )

Недумал я, что блоксхемы могут быть даже тут. С блоксхемами на много понятнее. Спасибо. Очень интересно.

Это не блок-схемы, а синтаксические диаграммы. Да, они полезные.

Для меня регулярки бывают двух видов - распространённые (валидация 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 возможен).

Ок, тогда вопрос в том, а обработает ли данных адрес почтовик того же Гугла, Эпла и тд? Обработает - это отправка и прием писем, без "отколупов" и попадания в папку "спам". Если нет - то вся обработка подобных адресов - бесполезна.

В принципе согласен - хотя зависит от сферы применения (скажем, проверяются ли адреса в формочке на сайте или где то на магистральном маршрутизаторе). Но определение, какие именно адреса фактически принимает Google/Apple - отдельная задача )

Лучшее, что читал про регулярные выражения. Точнее - лучшее изложение.

Прекрасная книга!

Это очень интересно, но вот ИМХО любую регулярку уже можно смело отдавать чатгпт и забыть про это.

Все равно если ты их не пишешь каждый день, ты их пишешь с гуглом и справочником. При этом практическая польза от скилла «умею читать/писать регулярки» сомнительная.

Умею читать от умею писать отличается ОЧЕНЬ сильно.

Мне они практически не нужны, использую ОЧЕНЬ редко, и, как мне кажется, для ситуативных случаев они хороши. Но вот разбираться с чужой (или старой своей, которой более полугода) - боль. Проще новую накидать.

И отдать её написать кому-то (той же нейронке) это равносильно тому, что разбираться в чужой (её же надо проверить). Спасибо, ни за какие деньги.

Очень удобны просто для разовой замены в редакторе. Для кода, который надо поддерживать, часто прав jwz:

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

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

По сути статьи, лучше примеры брать более жизненные. И раз уж примеры синтетические, то не нужна очень большая точность совпадения, а потому: `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.

Да, я понимаю, что примеры надуманные и нереалистичные. Но для меня главное была простота и последовательность изложения. Любой реалистичный пример ломает последовательность.

проходил это, когда курс писал, примеры приходилось из пальца высасывать, но, после объяснения скобок и квантификаторов, пффф... и тебе разбор CSV, и плавающие переносы в тексте, и триады в числах... желаю не перегореть ;)

при написании кода, в терминальной строке, в корректуре приходящих извне объемных данных...

Хорошие примеры, но всё это скорее разовые задачи, чем часть production кода - и подходы могут быть разные. Скажем, если надо быстренько посмотреть на какие-то паттерны в бинарном коде - наверное, пройдусь регулярками по выхлопу objdump -d. Если надо добавить такую фичу в продукт - скорее возьму для парсинга готовую библиотеку (скажем, из llvm), даже если на входе именно дизассемблированный текст.

Регулярки приятны тем, что не нужно уметь программировать, чтобы пользоваться sed/grep и обрабатывать массивы текста. Ну и поиск в Sublime, Libreoffice.

Был период, когда я мог писать регулярки, иногда довольно сложные, не заглядывая в доки и мануалы, а потом я перестал писать регулярки самостоятельно и начал даже иногда улыбаться!

Sign up to leave a comment.