Могут ли расширенные реализации регулярных выражений анализировать HTML? - PullRequest
5 голосов
/ 08 февраля 2011

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

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

Поскольку я не знаю деталей каких-либо конкретных реализаций, таких как perl, у меня следующие вопросы:

  1. Какие функции инструментов регулярных выражений не являются регулярными? Это обратные ссылки? И на каких языках они найдены?
  2. Достаточно ли какого-либо из этих дополнительных приемов для анализа всех контекстно-свободных языков?
  3. Если "нет" для # 2, то существует ли формальная категория или класс языков, которые эти дополнительные функции охватывают точно? Как мы можем быстро узнать, находится ли проблема, которую мы пытаемся решить, во власти наших не обязательно регулярных выражений?

Ответы [ 2 ]

12 голосов
/ 08 февраля 2011

Ответ на ваш вопрос заключается в том, что да, так называемые «расширенные регулярные выражения», которые, возможно, более правильно называть шаблонами, чем регулярные выражения в формальном смысле, такие как те, что встречаются в Perl и PCRE, действительно способен к рекурсивному синтаксическому анализу контекстно-свободных грамматик .

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

Второй подход, помеченный как wizardly, использует для анализа фактическую грамматику. Как таковой, он полностью такой же мощный, как и любой другой грамматический подход. Тем не менее, это также далеко за пределами возможностей подавляющего большинства случайных программистов. Это также рискует воссоздать идеальное колесо для получения отрицательной выгоды. Я написал это, чтобы показать, что можно сделать, но что практически ни при каких обстоятельствах не должно быть . Я хотел показать людям, почему они хотят использовать синтаксический анализатор в открытом X / HTML, показывая им, как чертовски сложно даже приблизиться к правильному подходу, даже используя некоторые из самых мощных доступных на данный момент средств сопоставления с образцом.

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

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

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

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

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

# delete all nested parens
s/\((?:[^()]*+|(?0))*\)//g;
2 голосов
/ 08 февраля 2011

Да, расширения в вопросах являются обратными ссылками, и они технически делают "регулярные выражения" NP-полными, см. параграф Википедии .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...