Подтвердить что ты не робот

Когда проблема слишком сложна для регулярного выражения?

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

Например: почему полная проверка подлинности электронной почты слишком сложна для регулярного выражения?

4b9b3361

Ответ 1

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

Ответ 2

Регулярные выражения представляют собой текстовое представление конечных автоматов. То есть они ограничиваются только нерекурсивным сопоставлением. Это означает, что у вас не может быть понятия "scope" или "sub-match" в вашем регулярном выражении. Рассмотрим следующую задачу:

(())()

Все ли открытые парсеры соответствуют близкому паре?

Очевидно, когда мы смотрим на это как на человека, мы можем легко видеть, что ответ "да". Однако никакое регулярное выражение не сможет надежно ответить на этот вопрос. Чтобы выполнить такую ​​обработку, вам понадобится полный pushdown automaton (например, DFA со стеком). Это чаще всего встречается в виде синтаксического анализатора, например, с помощью ANTLR или Bison.

Ответ 3

Несколько вещей, на которые нужно обратить внимание:

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

regexes, насколько я их люблю, не хороши в этих трех вещах. И помните, сохранить это просто! Если вы пытаетесь создать регулярное выражение, которое делает "все", тогда вы, вероятно, это неправильно.

Ответ 4

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

Возьмите адреса электронной почты (в соответствии с вашим примером). Это простое регулярное выражение (взятое из приятеля RegEx) соответствует 99% всех электронных писем:

\b[A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,4}\b

Это коротко и точно, и вы редко сталкиваетесь с проблемами. Однако, как отмечает собеседник RegEx, если ваш адрес электронной почты находится в редком домене верхнего уровня ".museum", он не будет принят.

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

Вот пример регулярного выражения, пытающегося придерживаться RFC 2822:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"
(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x
0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]
(?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)
{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08
\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Это, очевидно, становится проблемой уменьшения отдачи. Лучше использовать легко поддерживаемую реализацию, которая соответствует 99% адресов электронной почты по сравнению с монстром, который принимает 99,9% из них.

Регулярные выражения - отличный инструмент для использования в вашем программном блоке программистов, но они не являются решением всех ваших проблем с синтаксическим разбором. Если вы обнаружите, что решение RegEx начинает становиться чрезвычайно сложным, вам нужно либо попытаться логически разбить его на более мелкие регулярные выражения, чтобы соответствовать частям вашего текста, либо вам нужно начать искать другие методы для решения вашей проблемы. Точно так же есть простые проблемы, которые Регулярные выражения, из-за их природы, не могут решить (как сказал один плакат, не придерживаясь Regular Language).

Ответ 5

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

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

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

Ответ 6

Вот хорошая цитата из Раймонда Чена:

Не делайте регулярные выражения делать то, что им не нравится. Если вы хотите сопоставить простой шаблон, то сопоставьте простой шаблон. Если вы хотите сделать математику, тогда сделайте математику. Как сказал комментатор Мауриц: "Хитрость - не тратить время на разработку комбинационного молотка/отвертки, но просто используйте молоток и отвертку.

Источник

Ответ 7

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

Ответ 8

Уверенный знак, чтобы остановить использование регулярных выражений, таков: если у вас много фигурных скобок '()' и многих альтернатив '|' то это верный признак того, что вы пытаетесь выполнить (сложный) синтаксический анализ с помощью регулярных выражений.

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

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

Ответ 9

Наряду с огромными выражениями существуют основные ограничения на слова, которые могут обрабатываться с помощью регулярного выражения. Например, вы не можете писать regexp для слова, описываемого n символами a, а затем n chars b, где n может быть любым, более строго alt text.

В разных языках regexp является расширением Обычный язык, но время разбора может быть чрезвычайно большим, и этот код не переносится.

Ответ 10

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

  • Разбор HTML
  • Проверка подлинности электронной почты
  • Языковые парсеры

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

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

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

Ответ 11

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

Ответ 12

Мой предел - это шаблон регулярного выражения, длина которого составляет около 30-50 символов (зависит от количества фиксированного текста и количества команд регулярного выражения)

Ответ 13

Это может показаться глупым, но я часто жалуюсь, что не могу делать запросы к типам баз данных, используя регулярное выражение. Теперь особенно больше, чем раньше, потому что я постоянно вхожу в эти типы поисковой строки в поисковых системах. его очень трудно, если не невозможно, искать +complex AND +"regular expression"

Например, как мне искать в emacs для команд, которые имеют как Buffer, так и Window в их имени? Мне нужно искать отдельно для .*Buffer.*Window and .*Window.*Buffer