Пока вы следуете шаблону, в котором у вас есть 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'
;
Это шаблон регулярного выражения с комментариями, сделанный возможным с помощью модификатора x
. Тебе так легче понять.
Важным моментом является модификатор m
для многострочного режима. Шаблон должен работать в каждой строке, поэтому он заключен в ^
(Begin) и $
(End), что будет соответствовать началу и концу строки в многострочном режиме.
Когда вы выполните операцию замены, группа 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;