RegExp упражнение: неохотный квантификатор с прогнозным утверждением

Можете ли вы объяснить мне, как это работает? Вот пример:

<!-- The quick brown fox
jumps over the lazy dog -->

<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="/supersheet.css" />
<![endif]-->

<!-- Pack my box with five dozen liquor jugs -->

Сначала я попытался использовать следующее регулярное выражение для сопоставления содержимого внутри условных комментариев:

/<!--.*?stylesheet.*?-->/s

Не удалось, так как регулярное выражение соответствует всему содержимому до первого <!-- и последнее -->, Затем я попытался использовать другой шаблон с предварительным утверждением:

/<!--(?=.*?stylesheet).*?-->/s

Это работает и соответствует именно то, что мне нужно. Тем не менее, следующее регулярное выражение также работает:

/<!--(?=.*stylesheet).*?-->/s

Последнее регулярное выражение не имеет неохотного квантификатора в предварительном утверждении. И теперь я в замешательстве. Может кто-нибудь объяснить мне, как это работает? Может быть, есть лучшее решение для этого примера?

Обновлено:

Я попытался использовать регулярные выражения с утверждением в другом документе, но он не смог обработать содержимое между комментариями. Итак, этот /<!--(?=.*?stylesheet).*?-->/s (а также этот /<!--(?=.*stylesheet).*?-->/s) не является правильным. Не используйте его и попробуйте другие предложения.

Обновлено:

Решение было найдено Джонни 5 (см. ответ). Он предложил три варианта:

  1. Использование дефисированного дефиса для ограничения соответствия. Эта опция работает, только если между тегами нет дефиса. Если таблица стилей имеет URL /style-sheet.css, она не будет работать.
  2. Использование escape-последовательности: \K, Отлично работает. Недостатками являются следующие:
    • Это ужасно медленно (в моем случае это было в 8-10 раз медленнее, чем другие решения)
    • Доступно только с PHP 5.2.4
  3. Используя взгляд, чтобы сузить спичку. Это цель, которую я пытался достичь, но моего опыта использования косвенных утверждений было недостаточно для выполнения задачи.

Я думаю, что следующее является хорошим решением для моего примера:

/(?s)<!--(?:(?!<!).)+?stylesheet.+?-->/

То же самое, но с s модификатор в конце:

/<!--(?:(?!<!).)+?stylesheet.+?-->/s

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

Итак, окончательное решение заключается в следующем:

/<!--(?:(?!-->).)+?stylesheet.+?-->/s

Спасибо всем участникам за интересные ответы.

4

Решение

Соответствовать только части <!--stylesheet--> Есть много способов:

1.) Используйте отрицается дефис [^-] ограничить матч и остаться между <!-- а также stylesheet

(?s)<!--[^-]+stylesheet.+?-->

[^-] разрешает только символы, которые не являются дефисами. Увидеть тест на regex101.


2.) Чтобы получить «последний» или ближайший матч без особых усилий, также можно поставить жадный точка прежде чем ᗧ есть. Имеет смысл, если не соответствует глобально / только один элемент для сопоставления. использование \ K для сброса после жадности:

(?s)^.*\K<!--.+?stylesheet.+?-->

Увидеть тест на regex101. Также можно использовать захватить группу и захватить 1 доллар: (?s)^.*(<!--.+?stylesheet.+?-->)


3.) Используя смотреть вперед сужать его обычно дороже:

(?s)<!--(?:(?!<!).)+?stylesheet.+?-->

Увидеть тест на regex101. (?!<!). смотрит вперед на каждого персонажа между <!-- а также stylesheet если не начать другой <!… чтобы остаться внутри одного элемента. Похоже на отрицание дефиса.


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

2

Другие решения

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

<!--(?=.*?stylesheet).*?-->/s

Этот делает следующее:

  • Захватить <!--,
  • Смотри вперед, захватывая персонажей вплоть до stylesheet, Сбой, если не найден.
  • Захватывайте персонажи вплоть до -->,
<!--(?=.*stylesheet).*?-->/s

Этот делает следующее:

  • Захватить <!--,
  • Смотри вперед, захватывая любого персонажа, пока это уже невозможно. Вернуться назад, постоянно пытаясь соответствовать stylesheet, Сбой, если не найден.
  • Захватывайте персонажи вплоть до -->,

По сути, нужно значительно отказаться, а другой нет.

Если ваша тема вместо этого …

<! - Быстрая коричневая лиса
перепрыгивает через ленивую собаку ->

<! - [если IE 7]>
<ссылка rel = "таблицы стилей"type =" text / css "href =" / supersheet.css "/> <! [ENDIF] ->

<! - возьми мою коробку с пятью дюжинами таблицы стилейs ->

вы получите два разных результата. Первый найдет первый stylesheetв то время как последний найдет второй (и последний), так как он начинает поиск с конца строки.

2

По вопросам рекламы [email protected]