【问题标题】:Remove CSS rules dependent on RegEx Classes移除依赖于 RegEx 类的 CSS 规则
【发布时间】: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>');
}
?>

【问题讨论】:

    标签: php css regex sass


    【解决方案1】:

    回答

    简介

    根据您提供的示例,以下正则表达式可以使用,但是,它不适用于所有 CSS 规则。如果您添加更多案例,我可以更新正则表达式以适应其他情况。


    代码

    See regex in use here

    正则表达式

    (?:^|,\s*)\K(\.foo-bar)(?=\s*(?:,|{))
    

    替换

    UNUSED $1
    

    注意:使用多行m标志。


    用法

    以下脚本由regex101生成(通过点击regex101中的代码生成器):Link here

    $re = '/(?:^|,\s*)\K(\.foo-bar)(?=\s*(?:,|{))/m';
    $str = '.foo-bar {}
    
    .foo-bar, .bar-foo {}
    
    .foo-bar .bar-foo {}
    
    .boo-far, .foo-bar {}
    
    .foo-bar,.bar-foo {}
    
    .bar-foo.foo-bar {}';
    $subst = 'UNUSED $1';
    
    $result = preg_replace($re, $subst, $str);
    
    echo "The result of the substitution is ".$result;
    

    结果

    输入

    .foo-bar {}
    
    .foo-bar, .bar-foo {}
    
    .foo-bar .bar-foo {}
    
    .boo-far, .foo-bar {}
    
    .foo-bar,.bar-foo {}
    
    .bar-foo.foo-bar {}
    

    输出

    UNUSED .foo-bar {}
    
    UNUSED .foo-bar, .bar-foo {}
    
    .foo-bar .bar-foo {}
    
    .boo-far, UNUSED .foo-bar {}
    
    UNUSED .foo-bar,.bar-foo {}
    
    .bar-foo.foo-bar {}
    

    说明

    • (?:^|,\s*) 匹配以下任意一项
      • ^ 在行首断言位置
      • ,\s* 逗号字符 , 字面意思,后跟任意数量的空格字符
    • \K 重置报告匹配的起点(任何先前使用的字符都不再包含在最终匹配中)
    • (\.foo-bar) 捕获到第 1 组:点字符 . 字面意思,然后是 foo-bar 字面意思
    • (?=\s*(?:,|{)) 正向前瞻确保以下内容与以下内容匹配
      • \s* 任意空格字符任意次数
      • (?:,|{)) 匹配以下任意一项
        • , 逗号字符 , 字面意思
        • { 左大括号 { 字面意思


    编辑

    以下正则表达式是前一个正则表达式的更新,并将\s* 移到第一组之外,以匹配插入符号^ 之后的空格的可能性。

    (?:^|,)\s*\K(\.foo-bar)(?=\s*(?:,|{))
    

    【讨论】:

    • 这是一个很棒的答案,非常感谢您抽出宝贵的时间来做这件事。我遇到了这种情况,但是这不起作用。我在这里更新了 regex101 来演示 - regex101.com/r/gw46rn/2 第一个示例字符串也应该被捕获,但是缩进将其丢弃(在 SCSS 文件中它位于媒体查询中,因此是缩进)
    • @JoeCorby 不客气,我已对上述答案进行了更改(请参阅编辑)。更新了 regex101 链接:regex101.com/r/gw46rn/3
    • 再次感谢您!我做了最后一次修改,检查了一条冗余规则,其中一行上有多个适用的选择器,用于逗号和下一个选择器之间的空格,现在一切正常!
    猜你喜欢
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-05
    • 2018-06-01
    相关资源
    最近更新 更多