Regex: Lazy Worse?

Я всегда писал такие регулярные выражения

<A HREF="([^"]*)" TARGET="_blank">([^<]*)</A>

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

<A HREF="(.*?)" TARGET="_blank">(.*?)</A>

Есть ли недостаток в использовании этого второго подхода? Регулярное выражение определенно более компактно (даже SO лучше его анализирует).

Изменить. Здесь есть два лучших ответа, которые указывают на два важных различия между выражениями. ysth отвечает на слабость в не-жадном/ленивом, в котором сама гиперссылка может включать другие атрибуты тега A (определенно, не очень хорошо). Роб Кеннеди указывает на слабость в жадном примере: в тех якорях тексты не могут включать другие теги (определенно не все в порядке, потому что они не будут захватывать весь якорный текст)... так что ответ таков: регулярные выражения - это то, что они ленивые и нелазные решения, которые кажутся одинаковыми, вероятно, не семантически эквивалентны.

Изменить. Третий лучший ответ: Алан М относительно относительной скорости выражений. На данный момент я отмечу его как лучший ответ, чтобы люди дали ему больше очков.

Ответ 1

Еще одна вещь, которую следует учитывать, это то, как долго будет отображаться целевой текст, и сколько его будет соответствовать количественному подвыражению. Например, если вы пытались сопоставить весь элемент <BODY> в большом документе HTML, возможно, вы захотите использовать это регулярное выражение:

/<BODY>.*?<\/BODY>/is

Но это будет делать много ненужной работы, сопоставляя один символ за раз, эффективно делая отрицательный взгляд перед каждым. Вы знаете, что тег </BODY> находится очень близко к концу документа, поэтому разумная вещь - использовать обычный жадный количественный элемент; позвольте этому сложить весь остальной документ, а затем отбросить несколько символов, необходимых для соответствия концевому тегу.

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

Ответ 2

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

Нежелательное регулярное выражение будет соответствовать тем вещам, которые вы, вероятно, не хотите, например:

<A HREF="foo" NAME="foo" TARGET="_blank">foo</A>

где ваш первый. *? совпадения

foo" NAME="foo

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

Не жадный лучше, не так ли? Он работает вперёд, каждый раз проверяет соответствие и останавливается, когда находит его, тогда как нормальное закрытие kleene (*) работает в обратном порядке, сравнивая остальную часть ввода и удаляя вещи, пока не найдет совпадение.

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