我正在组合一些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);
}
然而,这个代码与之相反:
$path = '/themes/default/css/';
$search = '#url'('s*([''"]?)((http(s)?:)?//)#';
$replace = "url($1{$path}$2";
$css = preg_replace($search, $replace, $css);
我知道您可以使用类似!^(http)
的东西来而不是匹配以http
开头的字符串,但我尝试的所有操作都失败了(我在regex方面做得很糟糕)。我一直在使用在线regex测试仪来解决这个问题,但我真的被卡住了。
这可能不是我用来解决真正问题的方法(确保路径在编译的CSS中工作),但有人能帮助我解决这个regex问题,或者有更好的解决方案吗?
你就快到了-你追求的是"不匹配以"开头的字符串;被称为";负前瞻";并且看起来像CCD_ 8。
因此,对于后面没有's*['"]?(https?:)?//
的url'(
,您可以执行:
url'((?!'s*['"]?(http(s)?:)?//)
(我把(s)
捕获组放在那里,以备你想捕获它,但你不需要(s)
周围的括号;如果你不在乎捕获,s?
和(s)?
是一样的)。
请在此处查看它的实际操作。
编辑:
由于您想将$path放在引号(如果有的话)之后,我将regex修改为:
url'((?!'s*['"]?(?:https?:)?//)'s*(['"])?
即删除了我不关心的所有捕获括号,并添加了一个's*(['"])?
来捕获它是什么样的报价。
我认为它在这里的代码板中,但以防万一,这里是代码:
$path = '/themes/default/css/';
$search = '#url'((?!'s*[''"]?(?:https?:)?//)'s*([''"])?#';
$replace = "url($1{$path}";
此预匹配与所选答案一样好,但也支持原始数据
'#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);
完整示例
http://codepad.org/NDoya4NC
我通过以下模式(基于此处的其他答案)得到了这个结果:
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);
- 允许在支架周围留出空间
- 支持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;