Regex: ленивый хуже? - PullRequest
       36

Regex: ленивый хуже?

12 голосов
/ 14 декабря 2008

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

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

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

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

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

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

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

Ответы [ 6 ]

12 голосов
/ 15 декабря 2008

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

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

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

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

8 голосов
/ 14 декабря 2008

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

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

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

где твой первый. *? спички

foo" NAME="foo
7 голосов
/ 14 декабря 2008

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

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

3 голосов
/ 14 декабря 2008

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

1 голос
/ 14 декабря 2008

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

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

1 голос
/ 14 декабря 2008

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

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