1

我在 RegEx 方面获得了一些帮助,但不确定我做错了什么。我想要实现的是更改 CSS 文件中一个 CSS 属性的值,而不更改该 CSS 文件中的任何内容。

<?php
$var = '
#css {
    text-size: 14px;
    color: red;
    background: orange;
}
';
echo preg_replace('/#css(.*)color: (.*);(.*)}/is','#css$1color: black;$3 }',$var);
?>

我希望看到的结果是这样的:

#css {
    text-size: 14px;
    color: red;
    background: orange;
}

然而我得到的是:

#css {
    text-size: 14px;
    color: black;
 }

我根本不是 RegEx 方面的专家,但是在阅读了在线手册和示例之后,我认为我可以使用反向引用来做到这一点,并且第一场比赛的结果是 1 美元,第二场比赛的 2 美元,第三场比赛的 3 美元等等......在我的示例中,$1 匹配 '#css' 和 'color:' 之间的所有内容,然后我不使用 $2,因为我想将 'red' 替换为 'black'。我认为 3 美元将是 ';' 之间的所有结果 和 '}' 但它在某个地方迷路了,或者更可能的是,我在某个地方迷路了 ;-)

感谢您的建议和支持。

4

3 回答 3

3

首先,使用贪心.*总是有问题的。在您的情况下,它使用了太多符号,因此您会丢失背景,因为它与;代码中的最后一个匹配(在背景声明之后)。而是使用一个负字符类,该类匹配直到您知道的下一个符号不应该包含在匹配中 - 在您的情况下是;. 所以字符类应该是这样的:[^;]*. 匹配符号也是如此}- 改用负字符类。

其次,我会尽量减少捕获组的使用。

最后,我会减少混乱,并将您不想替换的所有内容放入捕获组之前和之后,以便您得到一个非常简单的结果:'$1black$2'

尝试以下正则表达式:

preg_replace('/(#css.*?color:)[^;]*([^}]*)/is','$1black$2',$var);

查看演示

请注意,此正则表达式有一个缺陷:如果您的声明中有不同color的 s(背景颜色、边框颜色、...),它将中断!因此,您应该包含一个额外的空格,以确保它只捕获“真实”color声明:

/(#css.*?\scolor:)[^;]*([^}]*)/is

如果每次意外(不应该发生)color:xyz;您的规则块中有多个声明,这仍然可能会中断。只有第一个被替换。

于 2013-11-12T08:36:53.977 回答
1

这里的问题是您正在为您的第二个捕获组贪婪地匹配。这样做时,它会消耗所有内容,直到文本中的最后一个分号。

你应该做的是使用惰性匹配组,而不是匹配尽可能少的字符。(例如,直到第一个分号,而不是最后一个分号)

preg_replace('/#css(.*)color: .*?;(.*)}/is','#css$1color: black;$2 }',$var);
于 2013-11-12T08:42:14.627 回答
0

据我了解您的问题,我认为这将解决您的问题。

$var = '
#css {
    text-size: 14px;
    color: red;
    background: orange;
}
';
preg_match_all('/(#css\s*\{[\sA-z0-9#:;-]*color\s*:\s*[A-z0-9#]*)/', $var, $output);

$temp = preg_replace('/(color\s*:\s*[A-z0-9#]*)/im', 'color: black', $output[0][0]);

echo preg_replace('/(#css\s*\{[\sA-z0-9#:;-]*color\s*:\s*[A-z0-9#]*)/im', $temp, $var);

?>
于 2013-11-12T08:42:23.827 回答