preg replace () regex для соответствия относительным путям url() в CSS-файлах
я объединяю некоторые CSS-файлы и записываю их в файл в отдельном каталоге. Я пытаюсь заменить relative url()
значения для работы с новым местоположением файла, игнорируя любые абсолютные URL-адреса. Вот пример CSS:
#TEST {
background:url(test.jpg);
background:url( 'test.jpg' );
background:url("test.jpg" );
background:url(http://example.com/test.jpg);
background:url('https://example.com/test.jpg');
background:url("http://example.com/test.jpg");
background:url( '//example.com/test.jpg' );
background:url( "//example.com/test.jpg" );
background:url(//example.com/test.jpg);
}
все, что не начинается с http://
, https://
или //
надо сделать $path
вводят перед ним (только первые 3 должны совпадать).
желаемый результат:
#TEST {
background:url(/themes/default/css/test.jpg);
background:url( '/themes/default/css/test.jpg' );
background:url("/themes/default/css/test.jpg" );
background:url(http://example.com/test.jpg);
background:url('https://example.com/test.jpg');
background:url("http://example.com/test.jpg");
background:url( '//example.com/test.jpg' );
background:url( "//example.com/test.jpg" );
background:url(//example.com/test.jpg);
}
однако, код соответствует противоположное:
$path = '/themes/default/css/';
$search = '#url(s*(['"]?)((http(s)?:)?//)#';
$replace = "url({$path}";
$css = preg_replace($search, $replace, $css);
Я знаю, что вы можете использовать что-то вроде !^(http)
to не сопоставление строк, которые начинаются с http
, но все, что я пробовал, потерпело неудачу (me === плохо в регулярном выражении). Я использовал онлайн тестер регулярных выражений чтобы выяснить это, но я действительно застрял.
это может быть не то, что я использую для решения реальной проблемы (убедившись, что пути работают в скомпилированном CSS), но может ли кто-нибудь помочь мне исправить это regex проблема, или есть лучшее решение?
4 ответов
вы почти там - то, что вы ищете для "не совпадающих строк, начиная с", называется "отрицательным взглядом" и выглядит как (?!http)
.
и url\(
не следует \s*['"]?(https?:)?//
, вы:
url\((?!\s*['"]?(http(s)?:)?//)
(Я сохранил это (s)
группа захвата там, если вы хотели захватить его, но вам не нужны эти скобки (s)
; s?
это то же самое, что (s)?
если вы не заботитесь о захвате).
посмотреть его в действии здесь.
Edit:
поскольку вы хотите поместить $ path после кавычки (если есть), я изменил регулярное выражение на:
url\((?!\s*['"]?(?:https?:)?//)\s*(['"])?
т. е. удалены все скобки захвата, о которых я не забочусь, и добавлен \s*(['"])?
захватить какую цитату Это.
Я думаю это в codepad здесь, но на всякий случай, вот код:
$path = '/themes/default/css/';
$search = '#url\((?!\s*[\'"]?(?:https?:)?//)\s*([\'"])?#';
$replace = "url({$path}";
этот pregmatch так же хорош, как выбранный ответ, но также поддерживает необработанные данные
'#url\((?!\s*([\'"]?(((?:https?:)?//)|(?:data\:?:))))\s*([\'"])?#'
вот строительные блоки этого длинного регулярного выражения
$absoluteUrl = '((?:https?:)?//)';
$rawData = '(?:data\:?:)';
$relativeUrl = '\s*([\'"]?((' . $absoluteUrl . ')|(' . $rawData . ')))';
$search = '#url\((?!' . $relativeUrl . ')\s*([\'"])?#';
$replace = "url({$path}";
echo preg_replace($search, $replace, $css);
полный пример
Я получил эту работу со следующим шаблоном (на основе других ответов здесь):
url\s*\(\s*[\'"]?(?!(((?:https?:)?\/\/)|(?:data\:?:)))([^\'"\)]+)[\'"]?\s*\)
PHP для его запуска:
$path = '/themes/default/css/';
$search = '%url\s*\(\s*[\\'"]?(?!(((?:https?:)?\/\/)|(?:data:?:)))([^\\'")]+)[\\'"]?\s*\)%';
$replace = 'url("' . $path . '/")';
$css = preg_replace($search, $replace, $css);
- позволяет пробелы вокруг скобок
- поддерживает отрицательный lookahead для http, https, data,"//"
- вставляет кавычки вокруг замененного актива
тест доступен здесь:https://regex101.com/r/zT2gM9/1
получил его на работу:
$sBaseUrl = 'http://example.com/';
$sCss = preg_replace_callback(
'|url\s*\(\s*[\'"]?([^\'"\)]+)[\'"]\s*\)|',
function($aMatches) use ($sBaseUrl) {
return 'url("'. $sBaseUrl . trim($aMatches[1]). '")';
},
$sCss
);
print $sCss;