PHP, регулярное выражение. Не работают квантификаторы при негативном просмотре

Задача такая: извлечь из поста ссылки на картинки (\<img src=...>), к которым не привязаны ссылки (\<a href=...>). Написала такую регулярку:

preg_match_all ( '#(?<!<a[^>]*>)<img[^>]+src="(.*?)"#' , $content , $matches);

То есть берём инфу из тэга \<img src>, если перед ним нет тэга \<a>.

Но внутри скобок для негативного просмотра не работает квантификатор *, функция вообще не срабатывает. Меняла его на +, {1,}, *? - тоже не работает. Что интересно, если написать конкретное число повторений, то всё отрабатывает правильно!

preg_match_all ( '#(?<!<a[^>]{68}>)<img[^>]+src="(.*?)"#' , $content , $matches);

Подскажите, это особенности негативного/позитивного просмотра, или я что-то неправильно пишу? Если там действительно нельзя задать произвольное число повторений, может, подскажете альтернативное решение?


Ответы (1 шт):

Автор решения: Wiktor Stribiżew

Вы можете использовать

$pattern = '#<a(?:\s[^>]*)?>.*?</a>(*SKIP)(*F)|<img[^>]+src="([^"]*)"#s';
if (preg_match_all($pattern, $content, $matches)) {
    print_r($matches[1]);
}

Как работает это выражение?

  • <a - текст <a
  • (?:\s[^>]*)? - опциональная последовательность пробельного символа и ноля и более символов, отличных от >
  • > - символ >
  • .*? - ноль и более символов, как можно меньше
  • </a> - текст </a>
  • (*SKIP)(*F) - то, что нашли, забудь и начни новый поиск с места, где сейчас находится индекс
  • | - или
  • <img - текст <img
  • [^>]+ - один и более символов, отличных от >
  • src=" - строка src="
  • ([^"]*) - Подмаска №1: ноль и более символов, отличных от "
  • " - символ ".
→ Ссылка