我正在组合一些CSS文件并将它们写入单独目录中的文件。我正在尝试替换相对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);
}
但是,this code与之相反:
$path = '/themes/default/css/';
$search = '#url\(\s*([\'"]?)((http(s)?:)?//)#';
$replace = "url($1{$path}$2";
$css = preg_replace($search, $replace, $css);
我知道您可以使用类似!^(http)
的 来匹配以http
开头的字符串,但我尝试过的所有内容都失败了(我= =正则表达式)。我一直在使用online regex tester来解决这个问题,但我确实陷入困境。
这可能不是我用来解决实际问题的方法(确保路径在编译的CSS中工作)但是任何人都可以帮我修复这个正则表达式问题,或者有更好的解决方案吗?
答案 0 :(得分:11)
你几乎就在那里 - 你所追求的“以不匹配的字符串开头”被称为“负向前瞻”并且看起来像(?!http)
。
因此,对于url\(
未跟\s*['"]?(https?:)?//
,您可以执行以下操作:
url\((?!\s*['"]?(http(s)?:)?//)
(我保留了(s)
捕获组,如果你想抓住它,但你不需要(s)
周围的那些括号; s?
与{{(s)?
相同1}}如果你不关心捕获)。
在行动here中查看。
由于你想把$ path放在引号后面(如果有的话),我把正则表达式修改为:
url\((?!\s*['"]?(?:https?:)?//)\s*(['"])?
即。删除了我不关心的所有捕获括号,并添加了\s*(['"])?
来捕获它是什么类型的引用。
我认为它在codepad here中,但以防万一,这是代码:
$path = '/themes/default/css/';
$search = '#url\((?!\s*[\'"]?(?:https?:)?//)\s*([\'"])?#';
$replace = "url($1{$path}";
答案 1 :(得分:4)
此pregmatch与所选答案一样好,但也支持原始数据
'#url\((?!\s*([\'"]?(((?:https?:)?//)|(?:data\:?:))))\s*([\'"])?#'
以下是该长正则表达式的构建块
$absoluteUrl = '((?:https?:)?//)';
$rawData = '(?:data\:?:)';
$relativeUrl = '\s*([\'"]?((' . $absoluteUrl . ')|(' . $rawData . ')))';
$search = '#url\((?!' . $relativeUrl . ')\s*([\'"])?#';
$replace = "url($6{$path}";
echo preg_replace($search, $replace, $css);
完整示例
答案 2 :(得分:1)
我使用以下模式(基于此处的其他答案):
url\s*\(\s*[\'"]?(?!(((?:https?:)?\/\/)|(?:data\:?:)))([^\'"\)]+)[\'"]?\s*\)
让它运行的PHP是:
$path = '/themes/default/css/';
$search = '%url\s*\(\s*[\\\'"]?(?!(((?:https?:)?\/\/)|(?:data:?:)))([^\\\'")]+)[\\\'"]?\s*\)%';
$replace = 'url("' . $path . '/$3")';
$css = preg_replace($search, $replace, $css);
答案 3 :(得分:0)
让它发挥作用:
$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;