XAKEPEHOK
@XAKEPEHOK

Странное поведение «негативного просмотра вперед». Пример RegExp'а внутри

Не могу понять причину. Подскажите пожалуйста. Задача: найти в CSS файле все свойства background, у которых в url задан относительный путь к изображению и сменить его на абсолютный. Url может быть обрамлен как одинарными, так и двойными кавычками. Url, начинающийся со слэша считается абсолютным.

Вот регулярка:
url\(("|')?(?!\w*?:?//|/)(.+?)("|')?\)

И вот что получается:

Пример №1
.class {
  background: url(images/bubbles.png) top repeat-x;
}

возвращает все правильно:
Group 1: no match
Group 2: images/bubbles.png
Group 3: no match

Пример №2
.class {
  background: url(/images/bubbles.png) top repeat-x;
  background: url(http://images/bubbles.png) top repeat-x;
}

возвращает все правильно: no match

Пример №3
.class {
  background: url('images/bubbles.png') top repeat-x;
}

возвращает все правильно:
Group 1: '
Group 2: images/bubbles.png
Group 3: '

Пример №4: беда. Стоит заключить абсолютный url в кавычки
.class {
  background: url('http://images/bubbles.png') top repeat-x;
}

получим
Group 1: no match
Group 2: 'http://images/bubbles.png
Group 3: '

Вопрос: почему первая группа совпадений пуста, вторая содержит кавычку и путь, в то время, как третья работает правильно?

P.S. Тестирую здесь. PHP 5.3 выдает тот же результат.
P.P.S. Мне не для парсинга чужих сайтов. Я допиливаю ExtendedClientScripts для Yii
  • Вопрос задан
  • 3737 просмотров
Пригласить эксперта
Ответы на вопрос 2
@egorinsk
Советую вам, чтобы делать регулярное выражение более стабильным и надежным, вместо точки явно задавать список символов, допустимых в url:

[^'"\\s]+?

А то, как поведет себя ваше выражение, без справочника по PCRE не разберешься.
Ответ написан
Wott
@Wott
Вопрос: почему первая группа совпадений пуста, вторая содержит кавычку и путь, в то время, как третья работает правильно?

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

В вашем случае где все необязательно я бы
включал бы в поиск url() — иметь надежный и статичный якорь эффективнее извените, как-то пропустил что он уже есть
жестче прописал бы условия на абсолютный урл типа |/
сделал бы поиск пути по типу ([^'")]+) — жадный до запрещенного символа работает быстрее и надежнее
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы