只要您遵循在行尾有 varname 并且每行仅包含 CSS property : value 的模式,您就可以使用基于正则表达式的搜索和替换来做到这一点。
如果您想这样做,请注意新值不包含 PCRE 意义上的任何换行符:\r\n|\n|\x0b|\f|\r|\x85(非 UTF-8 模式)。如果你不这样做,这会破坏你的解析器!
为此,您可以为模式创建一个掩码,以便稍后轻松插入变量名,我通常使用sprintf:
$patternMask =
'~
^ # start of line
(\s*[a-z]+:\s*)
# Group 1:
# whitespace (indentation)
# + CSS property and ":"
# + optional whitespace
(.*?) # Group 2: CSS value (to replace)
(\s*/\*\{%s\}\*/\s*)
# Group 3:
# whitespace (after value and before variable)
# + variable comment, %%s is placeholder for it\'s name
$ # end of line
# Pattern Modifiers:
# m: ^ & $ match begin/end of each line
# x: ignore spaces in pattern and allow comments (#)
~mx'
;
这是带有 cmets 的正则表达式模式,可通过 x-修饰符实现。只是为了让你更容易理解。
一个重要的点是用于多行模式的m-修饰符。该模式应该适用于每一行,因此它包含在^(开始)和$(结束)中,这将在多行模式下匹配行的开头和结尾。
当您进行替换操作时,第 2 组将被替换,第 1 组和第 3 组将被保留。完成后,结果仍将包含变量名。
然后通过使用sprintf 和preg_quote 在其中添加正确引用的变量名称,使用此掩码构建实际的正则表达式模式:
$varName = 'bgColor';
$value = '#f00 url(../images/bg-reg.jpg) repeat-x;';
# create regex pattern based on varname
$pattern = sprintf($patternMask, preg_quote($varName, $patternMask[0]));
$patternMask[0] 是 ~,因此如果您的变量名包含 ~,它将自动正确转义。
搜索模式现已完成。剩下的就是替代品了。作为变量名,替换字符串也需要转义以不破坏它的正则表达式(语法错误)。此外,如前所述,整个过程需要注意将新字符串保留为单行,否则下次执行替换操作会破坏它。因此,为了防止这种情况,任何换行符都将替换为 $value 中的一个空格以防止这种情况发生:
# replace characters that will break the pattern with space
$valueFiltered = str_replace(explode('|', "\r\n|\n|\x0b|\f|\r|\x85"), ' ', $value);
然后特殊字符\ 和$ 将被引用,这样它们就不会干扰替换模式并构建替换字符串。这是通过addcslashes 函数完成的:
# escape $ characters as they have a special meaning in the replace string
$valueEscaped = addcslashes($valueFiltered, '\$');
$replace = sprintf('${1}%s$3', $valueEscaped);
唯一剩下的就是运行替换操作,所以预先给它一些 CSS:
$css = <<<CSS
html,body {
background: #fff url(../images/bg.jpg) repeat-x; /*{bgColor}*/
color: #fff; /*{textColor}*/
}
CSS;
并使用preg_replace 运行替换:
$newCss = preg_replace($pattern, $replace, $css);
这已经是全部了。来自原始 CSS:
html,body {
background: #fff url(../images/bg.jpg) repeat-x; /*{bgColor}*/
color: #fff; /*{textColor}*/
}
到结果CSS:
html,body {
background: #f00 url(../images/bg-reg.jpg) repeat-x; /*{bgColor}*/
color: #fff; /*{textColor}*/
}
如果您使用preg_replace 的&$count 参数,您可以检查变量是否是字符串的一部分:
$newCss = preg_replace($pattern, $replace, $css, -1, $count);
$count 在给出的示例中为 1。
如果您想一次替换多个值,您可以使用数组作为$pattern 和$replace,以防万一。 $count 仍然是一个整数,所以它的用途可能有限。
整个代码一目了然:
$css = <<<CSS
html,body {
background: #fff url(../images/bg.jpg) repeat-x; /*{bgColor}*/
color: #fff; /*{textColor}*/
}
CSS;
$patternMask =
'~
^ # start of line
(\s*[a-z]+:\s*)
# Group 1:
# whitespace (indentation)
# + CSS property and ":"
# + optional whitespace
(.*?) # Group 2: CSS value (to replace)
(\s*/\*\{%s\}\*/\s*)
# Group 3:
# whitespace (after value and before variable)
# + variable comment, %%s is placeholder for it\'s name
$ # end of line
# Pattern Modifiers:
# m: ^ & $ match begin/end of each line
# x: ignore spaces in pattern and allow comments (#)
~mx'
;
$varName = 'bgColor';
$value = '#f00 url(../images/bg-reg.jpg) repeat-x;';
# create regex pattern based on varname
$pattern = sprintf($patternMask, preg_quote($varName, $patternMask[0]));
# replace characters that will break the pattern with space
$valueFiltered = str_replace(explode('|', "\r\n|\n|\x0b|\f|\r|\x85"), ' ', $value);
# escape $ characters as they have a special meaning in the replace string
$valueEscaped = addcslashes($valueFiltered, '\$');
$replace = sprintf('${1}%s$3', $valueEscaped);
$newCss = preg_replace($pattern, $replace, $css);
echo $newCss;