我想解析一个CSS文件,并且每次对{background:[some properties] right([12px)top(10px)[some properties];
进行background:[some properties] (12px) (10px) [some properties];
更改
我试过这个正则表达式:
(background\s*:.*?)\s(\d+([a-z]+|%|))\s+(\d+([a-z]+|%|));
但它抓住了:
background:url(../images/header.jpg) top no-repeat; height:123px; float:left; padding:65px left 0px top 0px 120px;
你可以在this fiddle中看到它应该捕获的唯一字符串是:
background:url(../images/header.jpg) 10px 0 no-repeat;
但它会捕获额外的字符串。
所以我的问题是如何在;
之后停止正则表达式模式,因此它不会继续下一个css规则。
和帽子是正确的模式吗?
答案 0 :(得分:2)
你可以试试这个:
$result = preg_replace('/\bbackground\s*:[^;]*?\K(\d+(?:px|e[mx]|%)?+\s+)(\d+(?:px|e[mx]|%)?+)/i', 'right $1 top $2', $string);
示例:
<?php
$string = <<<'LOD'
#banner{width:814px; background:url(../images/header.jpg) top no-repeat; height:123px; float:left; padding:65px 0px 0px 120px; font-family: Georgia, "Times New Roman", Times, serif; font-size:30px; color:#fff;}
#banner2{width:814px; background:url(../images/header.jpg) 10px 0 no-repeat; height:123px; float:left; padding:65px 0px 0px 120px; font-family: Georgia, "Times New Roman", Times, serif; font-size:30px; color:#fff;}
#banner3{width:814px; background:url(../images/header.jpg) left 10px top 0 no-repeat; height:123px; float:left; padding:65px 0px 0px 120px; font-family: Georgia, "Times New Roman", Times, serif; font-size:30px; color:#fff;}
LOD;
$result = preg_replace('/\bbackground\s*:[^;]*?\K(\d+(?:px|e[mx]|%)?+)\s+(\d+(?:px|e[mx]|%)?+)/i', 'right $1 top $2', $string);
print_r($result);
模式细节:
(?:....)
是非捕获组
\K
重置之前匹配结果中的所有匹配
\b
是一个单词边界。这是一个零宽度断言,\w
字符类的成员与另一个字符之间的边界
[^;]
是一个否定字符类,表示“除;
之外的所有字符”
量词在默认情况下是贪婪的(它可以捕获所有可能的),如果你希望它捕获的可能性较小(懒惰),你必须在(*?
,+?
之后添加一个问号, ??
,{1,5}?
)
答案 1 :(得分:0)
您的正则表达式希望background
属性以两个数字和;
结尾,并且不希望在那里遇到no-repeat
。试试这个正则表达式
(background\s*:.*?)\s(\d+([a-z]+|%|))\s+(\d+([a-z]+|%|)).*?;
答案 2 :(得分:0)
这应该有效:
(background\s*:[^;]*?)\s(\d+([a-z]+|%|))\s+(\d+([a-z]+|%|)).*?;
我已将第一个.*
替换为[^;]*
,或将替换为一个分号。这将阻止正则表达式遍历第一个分号,然后匹配您要查找的数值。
我还在最后的分号前添加了.*?
,以允许它遍历两个数值后的任何额外数据,例如示例中的“no-repeat”。如果您愿意,.*?
可以替换为[^;]*
。