- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在构建一个“主题生成器”,它将动态地即时编辑 CSS 文件。我认为使用 PHP 是最简单的选择(愿意考虑其他方法)。
我的 CSS 文件在每个属性后包含注释,如下所示:
html,body {
background: #fff url(../images/bg.jpg) repeat-x; /*{bgColor}*/
color: #fff; /*{textColor}*/
}
是否可以使用替换功能来搜索该评论并仅替换它之前的代码?用户可能希望在完成构建主题后返回并再次更改某些内容,因此评论必须始终保留。
谢谢
最佳答案
只要您遵循在行尾有 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
修饰符。该模式应该在每一行上工作,所以它被包含在 ^
(开始)和 $
(结束)中,这将匹配多行中一行的开始和结束模式。
当您进行替换操作时,组 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;
关于php - str_replace 基于 CSS 注释的 CSS 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8552154/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!