【发布时间】:2017-10-05 23:10:07
【问题描述】:
简介:
我对 RegEx 还很陌生,所以请多多包涵。我们有一个客户,他有一个非常大的 CSS 文件。总共有 27k 行——大约 20k 行是纯 CSS,以下是用 SCSS 编写的。我试图减少它,尽管花费了超过分配的时间来工作,但我发现它非常有趣 - 所以我写了一个小的 PHP 脚本来为我做这件事!不幸的是,由于 RegEx 有点麻烦,它并不完全存在。
上下文
remove.txt - 包含选择器的文本文件,逐行在我们的网站上是多余的,可以删除。 main.scss - 大的 SASS 文件。 PHP 脚本 - 基本上逐行读取 remove.txt 文件,在 main.scss 文件中找到选择器,并在每个选择器之前添加一个“UNUSED”字符串,这样我就可以逐行删除规则。
问题
所以这很麻烦的主要原因是因为我们必须在 CSS 规则的开头和结尾处考虑很多事件。例如 -
.foo-bar 的示例场景(粗体表示应该匹配的内容) -
.foo-bar {}
.foo-bar、.bar-foo {}
.foo-bar .bar-foo {}
.boo-far, .foo-bar {}
.foo-bar,.bar-foo {}
.bar-foo.foo-bar {}
PHP 脚本
<?php
$unused = 'main.scss';
if ($file = fopen("remove.txt", "r")) {
// Stop an endless loop if file doesn't exist
if (!$file) {
die('plz no loops');
}
// Begin looping through redundant selectors line by line
while(!feof($file)) {
$line = trim(fgets($file));
// Apply the regex to the selector
$line = $line.'([\s\S][^}]*})';
// Apply the global operators
$line = '/^'.$line.'/m';
// Echo the output for reference and debugging
echo ('<p>'.$line.'</p>');
// Find the rule, append it with UNUSED at the start
$dothings = preg_replace($line,'UNUSED $0',file_get_contents($unused), 1);
}
fclose($file);
} else {
echo ('<p>failed</p>');
}
?>
正则表达式
从上面你可以收集到我的 RegEx 将是 -
/^REDUNDANTRULE([\s\S][^}]*})/m
目前很难处理通常发生在媒体查询中的缩进,以及当有继续选择器应用于同一规则时。
从此我尝试添加到开始时(适合Whitespace以及选择器在较长版本的选择器中使用时) -
^[0a-zA-Z\s]
并将其添加到末尾(以适应逗号分隔选择器)
\,
任何 RegEx/PHP 向导都可以为我指明正确的方向吗?感谢您的阅读!
感谢@ctwheels 的精彩解释。我遇到了其他几个问题,一个是完全停止在接收到的冗余规则中使用而没有被转义。我现在已经更新了我的脚本以在查找替换之前转义它们,如下所示。现在这是我最新的工作脚本 -
<?php
$unused = 'main.scss';
if ($file = fopen("remove.txt", "r")) {
if (!$file) {
die('plz no loops');
}
while(!feof($file)) {
$line = trim(fgets($file));
if( strpos( $line, '.' ) !== false ) {
echo ". found in $line, escaping characters";
$line = str_replace('.', '\.', $line);
}
$line = '/(?:^|,\s*)\K('.$line.')(?=\s*(?:,|{))/m';
echo ('<p>'.$line.'</p>');
var_dump(preg_match_all($line, file_get_contents($unused)));
$dothings = preg_replace($line,'UNUSED $0',file_get_contents($unused), 1);
var_dump(
file_put_contents($unused,
$dothings
)
);
}
fclose($file);
} else {
echo ('<p>failed</p>');
}
?>
【问题讨论】: