Php 用正则表达式解析CSS
我正在创建一个CSS编辑器,并试图创建一个可以从CSS文档中获取数据的正则表达式。如果我有一个属性,这个正则表达式可以工作,但是我不能让它对所有属性都工作。我在PHP中使用preg/perl语法 正则表达式 预期结果 实际结果Php 用正则表达式解析CSS,php,css,regex,css-parsing,Php,Css,Regex,Css Parsing,我正在创建一个CSS编辑器,并试图创建一个可以从CSS文档中获取数据的正则表达式。如果我有一个属性,这个正则表达式可以工作,但是我不能让它对所有属性都工作。我在PHP中使用preg/perl语法 正则表达式 预期结果 实际结果 提前感谢您的帮助-整个下午我都很困惑 对于单个正则表达式来说,这似乎太复杂了。好吧,我相信有了正确的扩展,高级用户可以创建正确的正则表达式。但是你需要一个更高级的用户来调试它 相反,我建议使用正则表达式提取片段,然后分别标记每个片段。e、 g /([^{])\s*\{\s
提前感谢您的帮助-整个下午我都很困惑 对于单个正则表达式来说,这似乎太复杂了。好吧,我相信有了正确的扩展,高级用户可以创建正确的正则表达式。但是你需要一个更高级的用户来调试它 相反,我建议使用正则表达式提取片段,然后分别标记每个片段。e、 g
/([^{])\s*\{\s*([^}]*?)\s*}/
然后,将选择器和属性放在单独的字段中,然后将它们拆分。(即使是选择器解析起来也很有趣。)请注意,如果}出现在引号或其他内容中,即使这样也会带来麻烦。同样,您可以将其复杂化以避免这种情况,但在这里最好完全避免正则表达式,并通过一次解析一个字段来处理它,可能使用递归下降解析器或yacc/bison或其他任何方法。您试图从数据中提取结构,而不仅仅是单个值。正则表达式可能会被痛苦地拉伸以完成这项工作,但您实际上正在进入解析器领域,应该拿出大炮,即解析器
我从来没有使用过PHP解析器生成工具,但它们在轻松扫描文档后看起来还不错。退房并离开。LexerGenerator将使用一组正则表达式来描述一种语言(在本例中为CSS)中不同类型的标记,并输出一些识别单个标记的代码。ParserGenerator将获取一个语法,一个描述语言中哪些东西由哪些其他东西组成的描述,并输出一个解析器,一个代码,该代码将获取一组标记并返回一个语法树(您所追求的数据结构)。我建议不要使用正则表达式来解析CSS,尤其是在单个正则表达式中 如果您坚持在正则表达式中进行解析,请将其拆分为合理的部分-使用一个正则表达式拆分所有
body{..}
块,然后使用另一个正则表达式解析color:rgb(1,2,3);
属性
如果您实际上正在尝试编写一些“有用”的东西(而不是学习正则表达式),请寻找预先编写的CSS解析器
我发现这似乎很有效:
$cssp = new cssparser;
$cssp -> ParseStr("body { background: #f00;font: 12px Arial; }");
print_r($cssp->css);
…其输出如下:
Array
(
[body] => Array
(
[background] => #f00
[font] => 12px arial
)
)
解析器非常简单,所以应该很容易理解它在做什么。哦,我不得不删除读取if($this->html){$this->Add($VAR),”;}
(这似乎是一个遗留的调试内容)
我已经镜像了脚本,在上面的更改中,请不要使用您自己的正则表达式来解析CSS。 为什么要在代码等着你、准备好使用并且(希望)没有bug的时候重新发明轮子呢 有两个通常可用的类可以为您解析CSS: PEAR.php.net上的HTML_CSS PEAR包 及 PHPCLasses上的CSS解析器类:
我正在使用下面的正则表达式,它非常有效……当然,这个问题现在已经很老了,我看到你已经放弃了你的努力……但万一有人碰到它:
(?<selector>(?:(?:[^,{]+),?)*?)\{(?:(?<name>[^}:]+):?(?<value>[^};]+);?)*?\}
(?(?:(?:[^,{]+,?)*?)\{((?[^}::+):(?[^;]+);?)*?\}
(为了安全起见,hafta首先从CSS中删除所有的/*注释*/)试试这个
function trimStringArray($stringArray){
$result = array();
for($i=0; $i < count($stringArray); $i++){
$trimmed = trim($stringArray[$i]);
if($trimmed != '') $result[] = $trimmed;
}
return $result;
}
$regExp = '/\{|\}/';
$rawCssData = preg_split($regExp, $style);
$cssArray = array();
for($i=0; $i < count($rawCssData); $i++){
if($i % 2 == 0){
$cssStyle['selectors'] = array();
$selectors = split(',', $rawCssData[$i]);
$cssStyle['selectors'] = trimStringArray($selectors);
}
if($i % 2 == 1){
$attributes = split(';', $rawCssData[$i]);
$cssStyle['attributes'] = trimStringArray($attributes);
$cssArray[] = $cssStyle;
}
}
//return false;
echo '<pre>'."\n";
print_r($cssArray);
echo '</pre>'."\n";
函数trimStringArray($stringArray){
$result=array();
对于($i=0;$i
我写了一段很容易解析CSS的代码。你所要做的就是进行几次分解,实际上,$CSS变量是CSS的一个字符串。你所要做的就是打印($CSS)以获得一个完整解析的CSS数组
Array
(
[body] => Array
(
[background] => #f00
[font] => 12px arial
)
)
在Tanktalus当前答案的基础上,有几个改进和边缘案例需要注意 CSS解析正则表达式 此正则表达式将执行一些空间修剪,并点击一些额外的边缘情况,如本例所示: 键:值对;进一步复杂化正则表达式的陷阱 我也开始尝试划分key:value对,但很快发现,在每个选择器有多个样式的情况下,事情开始变得比我想要的更棘手。您可以在这里查看我尝试划分key:value的regex版本1,以及它如何在多个声明中失败: 实施 正如其他人提到的,您应该将其分解为多个步骤来解析和标记您的css 声明解析器 在获得第一组匹配项后,可以使用类似这样的方法来解析声明
([^:\s]+)*\s*:\s*([^;]+);
例如:
边缘案例
上面的示例对于多个声明非常有效,但可能只有一个声明没有分号结尾,这将在[大多数]浏览器中呈现,但会破坏这个正则表达式
著名案例
在有媒体查询的情况下,您可能还需要考虑嵌套规则
Array
(
[body] => Array
(
[background] => #f00
[font] => 12px arial
)
)
(?<selector>(?:(?:[^,{]+),?)*?)\{(?:(?<name>[^}:]+):?(?<value>[^};]+);?)*?\}
function trimStringArray($stringArray){
$result = array();
for($i=0; $i < count($stringArray); $i++){
$trimmed = trim($stringArray[$i]);
if($trimmed != '') $result[] = $trimmed;
}
return $result;
}
$regExp = '/\{|\}/';
$rawCssData = preg_split($regExp, $style);
$cssArray = array();
for($i=0; $i < count($rawCssData); $i++){
if($i % 2 == 0){
$cssStyle['selectors'] = array();
$selectors = split(',', $rawCssData[$i]);
$cssStyle['selectors'] = trimStringArray($selectors);
}
if($i % 2 == 1){
$attributes = split(';', $rawCssData[$i]);
$cssStyle['attributes'] = trimStringArray($attributes);
$cssArray[] = $cssStyle;
}
}
//return false;
echo '<pre>'."\n";
print_r($cssArray);
echo '</pre>'."\n";
$css_array = array(); // master array to hold all values
$element = explode('}', $css);
foreach ($element as $element) {
// get the name of the CSS element
$a_name = explode('{', $element);
$name = $a_name[0];
// get all the key:value pair styles
$a_styles = explode(';', $element);
// remove element name from first property element
$a_styles[0] = str_replace($name . '{', '', $a_styles[0]);
// loop through each style and split apart the key from the value
$count = count($a_styles);
for ($a=0;$a<$count;$a++) {
if ($a_styles[$a] != '') {
$a_key_value = explode(':', $a_styles[$a]);
// build the master css array
$css_array[$name][$a_key_value[0]] = $a_key_value[1];
}
}
}
Array
(
[body] => Array
(
[background] => #f00
[font] => 12px arial
)
)
\s*([^{]+)\s*\{\s*([^}]*?)\s*}