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

Регулярный компилятор выражения

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

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

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

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

Вопрос, который я хотел бы задать, - это такая вещь, как компилятор регулярных выражений? Или можно даже построить?

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

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

4b9b3361

Ответ 1

1) Perl разрешает коммутатору /x включать регулярные выражения, чтобы включить комментарии и пробелы внутри самого регулярного выражения. Это позволяет распространять сложное регулярное выражение на несколько строк, используя отступы для указания структуры блока.

2) Если вам не нравятся символы, похожие на линейный шум, не слишком сложно написать свои собственные функции, которые создают регулярные выражения. Например. в Perl:

sub at_start { '^'; }
sub at_end { '$'; }
sub any { "."; }
sub zero_or_more { "(?:$_[0])*"; }
sub one_or_more { "(?:$_[0])+"; }
sub optional { "(?:$_[0])?"; }
sub remember { "($_[0])"; }
sub one_of { "(?:" . join("|", @_) . ")"; }
sub in_charset { "[$_[0]]"; }       # I know it broken for ']'...
sub not_in_charset { "[^$_[0]]"; }   # I know it broken for ']'...

Затем, например, регулярное выражение для соответствия цитируемой строке (/^"(?:[^\\"]|\\.)*"/) становится:

at_start .
'"' .
zero_or_more(
    one_of(
        not_in_charset('\\\\"'),    # Yuck, 2 levels of escaping required
        '\\\\' . any
    )
) .
'"'

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

Ответ 2

Я никогда не натыкался на что-то подобное. И я не думаю, что что-то подобное было бы полезно.

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

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

Ответ 3

Как насчет того, чтобы написать их с Regex Buddy и вставить описание, которое оно генерирует в качестве комментария к вашему коду?

Ответ 4

Регулярные выражения (ну, "реальные" регулярные выражения, ни один из этих современных вещей;) - конечные автоматы. Таким образом, вы создаете синтаксис, который описывает регулярные выражения в терминах состояний, ребер, ввода и, возможно, вывода меток. fsmtools AT & T поддерживают что-то подобное, но они далеки от инструмента, готового для повседневного использования.

Язык в XFST, набор инструментов конечного состояния Xerox, также более подробен.

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

Ответ 5

Есть способы сделать REs в их обычной форме более читабельными (например, синтаксис perl /x) и несколько многословных языков для их выражения. См:

Я отмечаю, однако, что многие старые руки, похоже, им не нравятся.

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

Ответ 6

XML-схема "модель содержимого" - пример того, что вы хотите.

c(a|d)+r

может быть выражена как модель контента в XML-схеме как:

<sequence>
 <element name="c" type="xs:string"/>
 <choice minOccurs="1" maxOccurs="unbounded">
  <element name="a" type="xs:string"/>
  <element name="d" type="xs:string"/>     
 </choice>
 <element name="r" type="xs:string"/>
<sequence>

Relax NG имеет другой способ выразить ту же идею. Он не должен быть самим форматом XML (Relax NG также имеет эквивалентный синтаксис не XML).

Читабельность регулярного выражения снижается за счет всего необходимого экранирования, а формат, подобный приведенному выше, уменьшает необходимость в этом. Чтение регулярных выражений также уменьшается, когда регулярное выражение становится сложным, потому что нет систематического способа компоновки больших регулярных выражений из более мелких (хотя вы можете объединить строки). Модульность обычно помогает. Но для меня более короткий синтаксис чрезвычайно упрощен для чтения (я часто конвертирую модели содержимого XML Schema в regex, чтобы помочь мне работать с ними). ​​

Ответ 7

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

Ответ 8

Я вижу множество ответов, пытающихся решить проблему, но я думаю, что у меня есть ответ для вас.

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

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

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

Так что для компилятора я сомневаюсь, что когда-нибудь может быть такой. Как заметил дмкки, "я отмечаю, что многим старым рукам, похоже, не нравится". У вас есть мультфильмы и ситкомы, изображающие сложные математические уравнения на досках. Это шутка, чтобы показать, насколько трудно определенная тема, но на самом деле любой, кто имеет опыт, мог бы ее понять, если им дали подтекст и немного обучения. Regex не сложно. Как только вы получите основы, это просто сводится к конкретному парсеру, используемому вами. Его, как некоторые дети говорят мне, что они не хотят изучать C/С++, потому что это сложнее, чем Javascript, даже если он имеет тот же синтаксис. Его восприятие, а не трудность.

Как только вы узнали regex, его двигатели, которые дают вам проблемы. Visual Studio использует скобки вместо скобок для группировки. Простая библиотека регулярных выражений SLRE Я использую простое подмножество vs PCRE более полный синтаксис. На этом этапе мы начинаем говорить о более новом языке, а не о инструменте для сопоставления текста.

Кроме того, большинство программистов используют одну короткую строку для своих совпадений регулярных выражений, а не для создания полного соответствия регулярному выражению, потому что они просто хотят анализировать некоторые случайные данные. Соответствие регулярных выражений - это инструмент, например Bison, yacc или ANTLR. Ручной синтаксический анализатор всегда будет лучше, поэтому, по существу, вы можете скомпилировать собственное регулярное выражение, поэтому зачем тратить время на 2 страницы кода для регулярного выражения, когда простой цикл ansi c while быстрее?

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

В качестве дополнительной заметки обратите внимание на некоторые из Lua исходного кода между Lua 3.0 и 3.2.2. Они меняются с парсера Bison на ручной. Вы понимаете, насколько больше свободы у них есть, чем использование инструмента для разбора текста, особенно с последними выпусками функций. Конечно, он также усложняет код для обновления. Это был выбор между ясностью файлов *.y и надежностью ручной работы.

Ответ 9

Возможно, некоторые инструменты JavaScript могут помочь:

К сожалению, я не нашел готовых использовать инструмент "point and click" JS, чтобы легко создавать и управлять RegEx. Мощность RegEx (PCRE, Posix, Python) заключается в том, что они

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

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

Следующие могут быть полезны для других, но это не Linux, поэтому я не смог его протестировать:

Если вы найдете другие хорошие ссылки, возможно добавьте в качестве комментария. Я знаю, что это немного злоупотребление SO, чтобы запросить это, но это так невероятно полезно. Спасибо.

Ответ 10

Рассматривали ли вы использование генератора синтаксического анализатора (как компилятор компилятора), например ANTLR?

ANTLR также имеет некоторую среду IDE (ANTLR Works), где вы можете визуализировать/отлаживать парсеры.

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

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

Ответ 11

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

То, что вы не упоминаете в своем посте, но которое почти так же плохо, заключается в том, что почти каждый язык, редактор или инструмент имеет свои собственные вариации в синтаксисе regexp. Некоторые из них поддерживают синтаксис POSIX, как это было определено много лет назад, некоторые поддерживают синтаксис Perl, как и сегодня. Но у многих есть свои собственные независимые способы выражения вещей, или какие персонажи являются "особыми" (специальные символы - другая тема), а какие нет. Что скрывается, а что нет. И т.д. Не только трудно прочитать регулярное выражение, написанное для одного языка или инструмента, но даже если вы полностью запомните правила синтаксиса для своего любимого варианта, они могут отключить вас на другом языке, где {2,3} больше не будет означает то, что вы ожидаете. Это действительно беспорядок.

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

Итак, чтобы ответить на ваш вопрос, я часто думал о создании кросс-платформенной кросс-языковой библиотеки кросс-всего, которая позволит вам "переводить" из любого синтаксиса regexp (будь то Perl или POSIX, или Emacs и т.д.) в любой другой синтаксис regexp. Чтобы вам не пришлось беспокоиться, если регулярные выражения Python могут делать негативный внешний вид, или если скобки символьного класса должны быть экранированы в Emacs regexp. Вы могли бы просто запомнить один синтаксис, а затем вызвать вызов функции, чтобы получить эквивалентный синтаксис для того, что вы использовали.

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

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

Ответ 13

Если вы прочитали книгу Дракона для компиляторов, она предложит вам использовать регулярное выражение для анализа и анализа вашего языка более высокого уровня. Итак, регулярные выражения кажутся чем-то более низким уровнем. Я использую их очень часто в своих ежедневных задачах работы для разработки frontend/backend, и да, я нашел некоторые из них как бы загадочными. Тем не менее, это не делает неправильное регулярное выражение, вы всегда можете написать новый язык, если вам это не нравится, учитывая, что 1) у вас есть время 2) вы готовы приложить правильные усилия 3) сила сильна в пределах вы:)