7

我正在编写一个快速的 preg_replace 来从 CSS 中删除注释。CSS 注释通常有这样的语法:

/* Development Classes*/
/* Un-comment me for easy testing
  (will make it simpler to see errors) */

所以我试图杀死 /* 和 */ 之间的所有内容,如下所示:

$pattern = "#/\*[^(\*/)]*\*/#";
$replace = "";
$v = preg_replace($pattern, $replace, $v);

没有骰子!正斜杠似乎令人窒息,因为如果我将 /s 从模式中删除,我可以让它删除评论文本。我尝试了一些更简单的模式,看看我是否可以丢失斜杠,但它们返回原始字符串不变:

$pattern = "#/#";
$pattern = "/\//";

关于为什么我似乎无法匹配这些斜线的任何想法?谢谢!

4

4 回答 4

14

这是一个解决方案:

$regex = array(
"`^([\t\s]+)`ism"=>'',
"`^\/\*(.+?)\*\/`ism"=>"",
"`([\n\A;]+)\/\*(.+?)\*\/`ism"=>"$1",
"`([\n\A;\s]+)//(.+?)[\n\r]`ism"=>"$1\n",
"`(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`ism"=>"\n"
);
$buffer = preg_replace(array_keys($regex),$regex,$buffer);

取自 Samstyle PHP 框架中的脚本/样式表预处理器

请参阅:http ://code.google.com/p/samstyle-php-framework/source/browse/trunk/sp.php

csstest.php:

<?php

$buffer = file_get_contents('test.css');

$regex = array(
"`^([\t\s]+)`ism"=>'',
"`^\/\*(.+?)\*\/`ism"=>"",
"`([\n\A;]+)\/\*(.+?)\*\/`ism"=>"$1",
"`([\n\A;\s]+)//(.+?)[\n\r]`ism"=>"$1\n",
"`(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+`ism"=>"\n"
);
$buffer = preg_replace(array_keys($regex),$regex,$buffer);
echo $buffer;

?>

测试.css:

/* testing to remove this */
.test{}

csstest.php 的输出:

.test{}
于 2009-10-17T00:43:38.887 回答
7

我不相信你可以像你那样在否定字符类中使用分组。您将要使用的称为Assertions,其中有两种类型。“向前看”和“向后看”。

您在英语中寻找的模式基本上是,“正斜杠,文字通配符,任何后面没有正斜杠的东西,或者除了文字通配符后面跟着正斜杠或正斜杠之外的任何东西。 t 前面有文字通配符零次或多次、文字通配符、正斜杠"

<?php

$str = '/* one */ onemore
/*
* a
* b
**/
stuff // single line
/**/';

preg_match_all('#/\*(?:.(?!/)|[^\*](?=/)|(?<!\*)/)*\*/#s', $str, $matches);
print_r($matches);

?>
于 2009-10-17T15:26:11.500 回答
3

我遇到过同样的问题。为了解决这个问题,我首先通过将“/ASTERIX”和“ASTERIX/”替换为不同的标识符来简化代码,然后将它们用作开始和结束标记。

$code = str_replace("/*","_COMSTART",$code);
$code = str_replace("*/","COMEND_",$code);
$code = preg_replace("/_COMSTART.*?COMEND_/s","",$code);

/s 标志告诉搜索进入新行

于 2019-05-01T21:44:09.053 回答
0

只是为了好玩(当然是小项目),我制作了此类代码的非正则表达式版本(我希望它更快):

function removeCommentFromCss( $textContent )
{
    $clearText = "";
    $charsInCss = strlen( $textContent );
    $searchForStart = true;
    for( $index = 0; $index < $charsInCss; $index++ )
    {
        if ( $searchForStart )
        {
            if ( $textContent[ $index ] == "/" && (( $index + 1 ) < $charsInCss ) && $textContent[ $index + 1 ] == "*" )
            {
                $searchForStart = false;
                continue;
            }
            else
            {
                $clearText .= $textContent[ $index ];
            }
        }
        else
        {
            if ( $textContent[ $index ] == "*" && (( $index + 1 ) < $charsInCss ) && $textContent[ $index + 1 ] == "/" )
            {
                $searchForStart = true;
                $index++;
                continue;
            }
        }
    }
    return $clearText;
}
于 2017-04-24T01:21:08.273 回答