Почему регулярные выражения так болезненно привлекательны?

23

Выставка 1 , выставка 2 , думаю, вам не составит труда вспомнить другие примеры.

Дело в том, что если есть несколько способов решить проблему, программист PHP (я обычно просматриваю тег PHP в StackOverflow) запросит помощь в решении, включающем регулярные выражения.

Даже когда это будет менее экономично, даже если руководство по php предлагает ( ссылку ) использовать str_replaceвместо любой preg_*или ereg_*функцию, когда не требуются какие- либо необычные правила замены.

Кто-нибудь знает, почему это происходит?

Не поймите меня неправильно, некоторые из моих лучших друзей - регулярные выражения, и я не презираю Perl. Чего я не понимаю, так это того, почему не нужно искать альтернативы, даже когда перебор очевиден (регулярное выражение для переключения строк) или сложность кода возрастает экспоненциально (регулярное выражение для получения данных из html в PHP )

cbrandolino
источник
2
Возможно, вы захотите процитировать, что на самом деле говорит руководство php.
ChrisF
1
Потому что они загадочны, так что вы хотите стать частью эксклюзивного клуба Kewl Kidz? И главным образом потому, что они предоставляют короткий способ выражения соответствия или извлечения, для чего они и созданы. Конечно, для фиктивных случаев, пользовательский анализ, если лучше, но время разработки по сравнению с написанием быстрого регулярного выражения в пользу регулярного выражения.
Хайлем
Вы подчеркнули неправильную часть этого последнего предложения: возмутительная часть его "из html", а не "в PHP".
Изката

Ответы:

20

Почему регулярные выражения так болезненно привлекательны?

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

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

Крошечная вещь, содержащая магическую силу. Вы не можете сказать нет, не так ли?

user8685
источник
5
+1 - крошечная загадочная вещь, не меньше.
AJ Джонсон
Гобицы хитрые
Бен ДеМотт
49

Когда единственный инструмент, который у вас есть, это регулярное выражение, каждая проблема выглядит ^((?>[a-zA-Z\d!#$%&'*+\-/=?^_{|}~]+\x20*|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*"\x20*)*(?<angle><))?((?!\.)(?>\.?[a-zA-Z\d!#$%&'*+\-/=?^_{|}~]+)+|"((?=[\x01-\x7f])[^"\\]|\\[\x01-\x7f])*")@(((?!-)[a-zA-Z\d\-]+(?<!-)\.)+[a-zA-Z]{2,}|\[(((?(?<!\[)\.)(25[0-5]|2[0-4]\d|[01]?\d?\d)){4}|[a-zA-Z\d\-]*[a-zA-Z\d]:((?=[\x01-\x7f])[^\\\[\]]|\\[\x01-\x7f])+)\])(?(angle)>)$

glenatron
источник
16
Соблазн выбрать этот ответ очень силен, но я думаю, что должен сопротивляться, так как это мой первый вопрос, открытый здесь, и я должен на некоторое время притвориться серьезным.
cbrandolino
1
@Dev, в этом много смысла. Мой комментарий был просто забавным способом выразить мою признательность за ответ.
cbrandolino
17
Что на земле это соответствует?
Том О'Коннор
4
Я не знаю ... Я думаю, что это в значительной степени подводит итог всего этого. Если вы знаете регулярные выражения и не знаете о других методах, зачем вам искать? У вас уже есть инструмент, который, если все сделано правильно, справится с работой. До тех пор, пока они не наткнутся на более простой метод или ему не сообщат об этом, регулярное выражение будет универсальным методом, даже если он будет более сложным, чем это необходимо.
Aeo
4
@ Tom O'Connor Я думаю, что это что-то похожее на Regex для сопоставления адреса электронной почты RFC 2822, но мне пришлось убрать пару символов, потому что они наносили ущерб уценке.
Гленатрон
23

Я думаю это потому что:

  1. Они фантастически лаконичны (при правильном использовании) по сравнению с эквивалентным кодом, и
  2. Они широко поддерживаются в разных языках программирования, поэтому большинство разработчиков знакомы с ними.
hallidave
источник
3
№ 2 имеет смысл.
cbrandolino
23

На ранних этапах моей карьеры (например, до PHP) я был гуру Perl, и одним из основных аспектов Perl gurudom является овладение регулярными выражениями.

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

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

Дэн Рэй
источник
2
Я не могу высказать это достаточно.
CaffGeek
8
Мне любопытно: вы читаете регулярные выражения так же свободно, как пишете их?
peterchen
7
Я надеюсь, что вы регулярно проводите тренинги по регулярным выражениям и / или документируете свой код; в противном случае вы создаете кошмар поддержки для своих коллег. Время, которое вы сэкономили, написав это регулярное выражение, может быть потеряно сто раз людьми, пытающимися понять, что делает это «элегантное регулярное выражение».
Джефф Кнехт
3
Так здорово. Прямо здесь, в этих комментариях, вы можете услышать перетягивание каната между любящими и ненавидящими регулярными выражениями.
Дэн Рэй
1
@Ben Lee: Думаю, да - ОТО, я никогда не сталкивался с комментируемым регулярным выражением в дикой природе. Некоторые проблемы с регулярными выражениями могут быть основаны на хладнокровии.
peterchen
16

Наоборот. Люди попугаи регулярные выражения являются злым мемом слишком часто ИМО. Очевидно, что preg_match используется phpслишком часто, но менее очевидно, что часто это целесообразно (в PHP).

Я бы зашел так далеко и предположил, что это еще одна микрооптимизация в php land для использования строковых функций. Есть много и много полезных, и они, как правило, лучший выбор. Но вы не должны избегать preg_matchв пользу множества strposи ifцепей. Поскольку на практике оказывается, что libpcre часто быстрее, чем PHP может выполнить цикл поиска строковых альтернатив, например

В качестве недавнего примера я понял, что проверка строки в нижнем регистре:

 if ($string == strtolower($string))

Это более читабельно, чем:

 if (!preg_match("/[A-Z]/", $string))

И вы могли бы предположить, что первый должен быть быстрее, так как он полностью PHP. Но на самом деле регулярное выражение просматривает строку только один раз и может отменить отрицательное условие, как только обнаружит заглавную букву. Однако подход strtolower () просматривает строку дважды. Сначала strtolower () дублирует строку, перебирая каждую букву, сравнивая и заглавные буквы. Затем ==перебирает оригинал и копию, сравнивая их еще раз.

Так что это не очевидный случай. И чтобы быть объективным, первое часто быстрее, так как обычно вы просто сравниваете короткие строки. Но не следует слепо исходить из предположения, что строковые функции PHP всегда рекомендуются для регулярных выражений.

(Я испытываю желание добавить еще одну громкую речь о забавном ответе @ bobince относительно xhtml-регулярных выражений и о том, как это в последнее время часто связано очень бесполезным образом. А более объективные ответы ниже игнорируются.)

марио
источник
1
Я согласен с вашим примером; тем не менее, в данном конкретном случае я бы предпочел «strtolower ()» в любом случае: в некритическом коде даже такая большая (по сравнению с другой реализацией) оптимизация времени выполнения незначительна - если только вы не хотите оценить строчные буквы Это огромный текстовый файл, но я не могу представить, чтобы это было полезно.
cbrandolino
1
@cbrandolino: нет обсуждения. Этот материал должен быть релевантным и оцененным только для вложенных циклов, где это может иметь фактическое значение.
Марио
4
+1 За то, что люди всегда их избивают, гораздо больше, чем их поддерживают.
Orbling
1
Как один из «операторов регулярных выражений»: забавно видеть, что однострочные более или менее выражают то, для чего «ручной» разбор строк требует 30 строк. Тем не менее, обслуживание страдает в большинстве реалистичных примеров. Кроме того, при попытке применить их к неподтвержденному вводу генерация подходящей диагностики для отклоненного ввода требует дополнительной акробатики. Для меня это прототипный код «только для записи» - круто для быстрых скриптов, отстой для долгоживущих приложений.
peterchen
1
Любой, кто не пишет все свои регулярные выражения в /xрежиме, позволяющем выделить пробел для локтя когнитивного разделения, и для комментариев, объясняющих, почему что-то делается, должен, конечно, уложить свои уши. Но для реальных регулярных выражений разумной сложности вам необходимо рассмотреть возможность применения дизайна сверху вниз с помощью грамматических регулярных выражений . Как только вы увидели свет, вы никогда не вернетесь к /@#$^^@#$^&&*)@#/.
2012 года
8

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

У них есть следующие преимущества:

  • Они лаконичны . Обычно для анализа конкретного обычного языка требуется гораздо больше кода с использованием определенного алгоритма, который вы придумали, чем с помощью регулярного выражения.
  • Они быстры в использовании. Как правило, для написания синтаксического анализатора для определенного обычного языка требуется гораздо больше времени с использованием определенного алгоритма, который вы придумали, чем для регулярного выражения.
  • Они легки . Как только вы изучите набор специальных символов и их значения, вы сможете легко составить регулярное выражение (хотя его будет немного сложнее читать). Регулярные выражения сами по себе являются языками - полезная черта, потому что наш вид эволюционировал, чтобы очень хорошо владеть языком.
  • Они быстрые . После компиляции они могут соответствовать длине строки Nза O ( N).
  • Они гибкие . Они могут соответствовать любому обычному языку, и большая часть наших данных выражается как обычный язык.
  • Они вездесущи . Большинство языков программирования имеют базовую поддержку регулярных выражений - либо через внешние библиотеки, либо встроенные в сам язык. Существует также не слишком много различий между самими языками регулярных выражений.

Это делает их привлекательными для ситуаций, в которых они подходят, но люди могут использовать их в ситуациях, когда они не лучший инструмент, потому что они:

  • Не понимаю, что то, что они соответствуют, не может быть выражено с помощью регулярного выражения (например, HTML).
  • Они ленивы (плохо) - они знают инструмент и признают, что это не лучший инструмент для того, что они делают, но он будет работать без проблем 95% времени и отнимает 95% усилий на изучение конкретного парсер или пишущий с нуля.
  • Они не знают, что существуют лучшие инструменты.
оборота david4dev
источник
Я имел в виду некоторые конкретные случаи, в которых они, очевидно, не лучший способ продолжить, но все еще используются. Я люблю регулярные выражения (я имею в виду, я нахожу их скучными и безжизненными, но все же очень полезными в некоторых контекстах) и знаю, в чем их преимущества.
cbrandolino
Я согласен с остальными, но быстро и легко? Кривая обучения крутая: для новичка трудно понять, почему выражение не работает, и каждая реализация regexp, кажется, имеет по крайней мере тонкие различия, так что вы должны следить за тем, где вы пытаетесь учиться.
peterchen
Почему все путают извлечение маленьких кусочков HTML с полным разбором полноценной веб-страницы в полное дерево разбора? Это действительно глупо. Поверьте, когда я редактирую HTML-страницы vi, вы ставите свою жизнь, которую я использую :%s/foo/bar/gcна этом. Если это достаточно хорошо для редактора, это достаточно хорошо для сценария.
2012 года
6

Хм, я могу только догадываться. Возможно, некоторые люди сталкивались с тем, что 30 строк их кода были заменены регулярным выражением длиной 20 символов, поэтому для них было бы неправильным использовать что-либо другое вместо использования регулярных выражений.

оборота user281377
источник
4

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

Леннарт Регебро
источник
6
С точки зрения нашей эволюционной истории, которая стоит перед разумом. Мы сопоставляли паттерны задолго до того, как определяли грамматику или открывали силлогизмы.
Гленатрон
1
Я не согласен, программирование включает в себя логику и сопоставление с образцом, две области. Регулярные выражения очень хороши в сопоставлении с образцом и должны использоваться для таких задач. Сказать «мне они не нравятся» - значит выбросить хороший инструмент для конкретной работы.
Orbling
@ Orbling: Вопрос не в том, хорошие они или плохие, а в том, почему некоторые люди злоупотребляют ими, а другие нет.
Леннарт Регебро
Вопрос может быть, но ваш ответ предполагает, что в игре задействован тот или иной тип ума, а не оба.
Orbling
Я не думаю, что «предложить» является правильным словом.
Леннарт Регебро
3

Я думаю, что повсеместное использование регулярных выражений связано с вездесущностью строк. Строка - это самая простая структура данных, первая, которую большинство из нас изучает. Поскольку весь наш код написан в символической форме, для программиста естественно подумать о моделировании чего-либо в символической форме. Но если наш язык программирования оказывает какое-либо сопротивление, когда мы пытаемся расширить его синтаксис для наших умных новых символических форм, они все заканчиваются между кавычками. Реляционная модель данных имеет SQL. Модель данных XML имеет XQuery. Но как насчет скромной строковой модели данных? Regex!

Буквально вчера я просматривал API для новой блестящей платформы Javascript, поддерживающей разработку игр на HTML5. У него есть декларативный механизм для описания основных подсистем, которые понадобятся вашей игре. Как определить эти функции? JSON? Свободное обозначение точки? Массив? Нет - строка, содержащая список имен элементов, разделенных запятыми и пробелами. Интересно, как он разбирает этот список ...?

WReach
источник
2

Потому что вы можете увидеть все это сразу. Увидев все это, легче работать, и это всегда приятно. Это похоже на причину, по которой многие программисты на C ++ все еще используют операторы printf-типа: это не типобезопасно (хотя gcc по крайней мере может проверять типы в операторах printf), и это не красиво, но мальчик компактен и удобен в использовании.

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

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

Майкл Кон
источник
2

Хм, текущие ответы слишком сосредоточены на технических аспектах и ​​на плюсах / минусах читабельности (что является важным моментом). Итак, позвольте мне попытаться перенести это немного больше в среду / сообщество PHP:

  • PHP - маленькая сводная сестра Perls . И неотъемлемой частью Perl являются регулярные выражения (они же это изобрели, не так ли?). Поэтому это одна из причин, почему регулярные выражения распространены и в PHP.
  • Случай использования РНР является совпадению не так много , в отличие от случая использования регулярных выражений. PHP структурно используется для склейки HTML-страниц. И регулярные выражения работают над текстом. (что сказал WReach)
  • Микро оптимизация . Как упоминалось ранее: люди используют регулярные выражения и / или строковые функции PHP часто после ощутимой скорости. Основная проблема в кругах PHP, не специфичная для регулярных выражений.
  • Регулярные выражения встроены . В Python, в Java, в C #, в Ruby? есть доступность, но сдерживающий фактор необходимости загружать дополнительный модуль. И посмотрите, как в PHP или Javascript, где это является основной функцией, шаблон использования отличается. Еще один экспонат: CSS, где он все чаще используется.
  • Руководство по PHP виновато. Это часто так. Регулярные выражения легко обнаружить, и я отложил этот забавный факт, потому что он скучен в своей очевидности: все проклятые учебники и вводные книги по PHP всегда учат регулярным выражениям, но не учат по случаям использования.
  • Строка API в PHP был разработан теми же самыми людьми , которые принесли вам волшебные кавычки и пространства имен \ разделитель. Он всеобъемлющий, лучше, чем Java, но не гламурный в целом. В частности, если строки могут удваиваться как объекты (см. Python), строковые функции могут превосходить регулярные выражения.

Но это как примечания стороны. Я считаю, что в любом случае это в основном воспринимаемые и технические причины, которые приводят к чрезмерному использованию и / или избеганию регулярных выражений в целом. Тем не менее, PHP и его пользовательская база имеют несколько свойств, которые его объединяют, и почему мы видим больше вопросов о SO [цитата нужна!], И они там «болезненно привлекательны».

марио
источник
1

Мне нравятся регулярные выражения в целом, мне они легче читать / понимать, чем те 20 строк кода, которыми мне пришлось бы их заменить. Короткие регулярные выражения быстро читаются и понимаются, и их относительно легко поддерживать (если выражение изменяется, у вас есть только одна строка для изменения по сравнению с просмотром 20 строк кода для внесения изменений). Есть моменты, когда они используются не по назначению, но и многие другие.

Причина, по которой вы, вероятно, видите такое сильное злоупотребление ими, заключается в том, что вы просматриваете PHP-раздел StackOverFlow, поскольку, я уверен, вы знаете, что существует множество незрелых PHP-программистов.

stoj
источник
1

Почему регулярные выражения так болезненно привлекательны?

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

Теперь, как говорится, я возвращаюсь к отладке небольшого Perl-приложения. Не могу с этим поделать; к сожалению, иногда они остаются лучшим инструментом для работы.

Ладья
источник
4
Я люблю говорить, что регулярные выражения не являются ни «регулярными», ни «выразительными»
Эндрю Барбер
2
Они безобразны и непонятны, если вы их не понимаете. Как только вы достигнете дзен регулярных выражений, они действительно будут довольно элегантными.
Дэн Рэй
1
-1 Для того, чтобы решить, что все программисты любят быть неясными, а затем не рассматривать любые другие возможные объяснения. ... Заявление, почему вы думаете, что они безобразны или непостижимы, помогло бы.
Макнейл
1
@Macneil - Пожалуйста, (хотя да, мои мысли совпадают), если вы не цитируете меня, не говорите, что я сказал / решил что-то, что я не сделал (первая часть вашего комментария). Насколько ваш вопрос, вы находите их красивыми ?! ... Я не. А поскольку это субъективный сайт, и это субъективное мнение, мне не нужно и не хочу его развивать. И я не буду пытаться, в этом отношении.
Ладья
1
@Rook - я думаю, что большинство людей смотрят на сложное регулярное выражение, решают, что все регулярные выражения некрасивы, а затем перестают думать. Дело в том, что они очень элегантный и выразительный инструмент, если вы можете изложить свои предубеждения по поводу них. Кстати, по вашей собственной логике, многие программисты не могут заниматься алгеброй, поэтому алгебра, вероятно, изначально присуща злу и должна быть отменена, поскольку она явно не очень понятна.
Дэн Рэй
0

Человек - существо, использующее инструменты, а регулярные выражения - мощные инструменты. Хорошая метафора для регулярных выражений - кусочек мяса из гастронома. Если вы хотите тонкие кусочки индейки, солонины и т. Д., То это просто вещь. Однако вам нужны умелые руки, чтобы использовать его, потому что вы можете по-настоящему сильно порезаться им, и вы ничего не почувствуете, пока не увидите кровь. Под этим я подразумеваю то, что большая проблема с регулярными выражениями состоит в том, чтобы слегка их отключить, означает, что вы сопоставляете то, что не должны, или наоборот, и не узнаете, пока это не вызовет проблему в дальнейшем.

Ларри Коулман
источник
0

Регулярные выражения очень привлекательны, потому что они обладают властью. Вы можете сделать очень сложную работу в очень мало символов.

Проблема заключается в том, что стандартная конструкция регулярного выражения не является полной по Тьюрингу, что означает, что существуют программы, которые вы просто не можете реализовать с помощью регулярного выражения, и люди не ЗНАЮ этого, когда их завлекает очевидная сила регулярных выражений.

Это - я полагаю - причина jwz-цитаты «теперь у них две проблемы».

Я предполагаю, что регулярные выражения Perl полны по Тьюрингу, но, видимо, они еще не были окончательно доказаны или опровергнуты.

user1249
источник
0

Потому что это эффективный способ программирования конечного автомата, который является мощным инструментом, когда он применяется. Это в основном свой собственный язык для программирования автоматов FSM, который полезен, если вы знаете язык, раздражает, если вы не знаете.

DanTilkin
источник
0

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

То же самое можно сказать о Perl, awk, Linux и всем, что не имеет блестящих кнопок или приятного цветного синтаксиса. Таким образом, это как дополнительная сложность для «тривиальных задач», просто бросить несколько циклов, разбиений, переключателя, немного магии и все, что-то, что может сработать. Но хорошо, если вы находитесь на другой стороне дороги, регулярные выражения - это красивые формочки для печенья, которые выглядят как сигнальные шумы без каких-либо неприятных циклов или дополнительных вещей для отладки. Я люблю их также за гибкость, которую они обеспечивают. Когда шаблон для соответствия меняется, вы просто меняете регулярное выражение, а не алгоритм или инструмент / что угодно, и это хорошо и снова работает. А так как они являются волшебной строкой, вы можете поместить ее вне исходного кода, если хотите. И еще одна вещь, которая заставляет меня думать о Perl: если вы пишете регулярное выражение длиной более 20 символов, вам кажется, что вы многого достигли, по крайней мере для меня, это так аккуратно и компактно. Я также ленивый программист, мне не нравится писать много кода с хорошими ссылками и комментариями и добавлять некоторые ошибки в микс.

alfa64
источник