代码之家  ›  专栏  ›  技术社区  ›  benlumley

从PHP代码中自动删除注释的最佳方法

  •  42
  • benlumley  · 技术社区  · 16 年前

    从PHP文件中删除注释的最佳方法是什么?

    我想做类似于strip-whitespace()的事情,但它不应该删除换行符。

    如:

    我想要这个:

    <?PHP
    // something
    if ($whatsit) {
        do_something(); # we do something here
        echo '<html>Some embedded HTML</html>';
    }
    /* another long 
    comment
    */
    some_more_code();
    ?>
    

    成为:

    <?PHP
    if ($whatsit) {
        do_something();
        echo '<html>Some embedded HTML</html>';
    }
    some_more_code();
    ?>
    

    (尽管如果删除注释时空行仍然存在,那就不好了)。

    这可能是不可能的,因为需要保留嵌入的HTML——这正是Google上出现的问题的绊脚石。

    11 回复  |  直到 6 年前
        1
  •  50
  •   Ionuț G. Stan    14 年前

    我会用 tokenizer . 这是我的解决方案。它应该同时适用于php 4和5:

    $fileStr = file_get_contents('path/to/file');
    $newStr  = '';
    
    $commentTokens = array(T_COMMENT);
    
    if (defined('T_DOC_COMMENT'))
        $commentTokens[] = T_DOC_COMMENT; // PHP 5
    if (defined('T_ML_COMMENT'))
        $commentTokens[] = T_ML_COMMENT;  // PHP 4
    
    $tokens = token_get_all($fileStr);
    
    foreach ($tokens as $token) {    
        if (is_array($token)) {
            if (in_array($token[0], $commentTokens))
                continue;
    
            $token = $token[1];
        }
    
        $newStr .= $token;
    }
    
    echo $newStr;
    
        2
  •  37
  •   Paul Dixon    16 年前

    如何使用php-w生成一个去掉注释和空白的文件,然后使用类似于 PHP_Beautifier 为了可读性重新格式化?

        3
  •  8
  •   John Tyler    13 年前

    下面是上面发布的函数,它被修改为递归地从一个目录及其所有子目录中的所有PHP文件中删除所有注释:

    function rmcomments($id) {
        if (file_exists($id)) {
            if (is_dir($id)) {
                $handle = opendir($id);
                while($file = readdir($handle)) {
                    if (($file != ".") && ($file != "..")) {
                        rmcomments($id."/".$file); }}
                closedir($handle); }
            else if ((is_file($id)) && (end(explode('.', $id)) == "php")) {
                if (!is_writable($id)) { chmod($id,0777); }
                if (is_writable($id)) {
                    $fileStr = file_get_contents($id);
                    $newStr  = '';
                    $commentTokens = array(T_COMMENT);
                    if (defined('T_DOC_COMMENT')) { $commentTokens[] = T_DOC_COMMENT; }
                    if (defined('T_ML_COMMENT')) { $commentTokens[] = T_ML_COMMENT; }
                    $tokens = token_get_all($fileStr);
                    foreach ($tokens as $token) {    
                        if (is_array($token)) {
                            if (in_array($token[0], $commentTokens)) { continue; }
                            $token = $token[1]; }
                        $newStr .= $token; }
                    if (!file_put_contents($id,$newStr)) {
                        $open = fopen($id,"w");
                        fwrite($open,$newStr);
                        fclose($open); }}}}}
    
    rmcomments("path/to/directory");
    
        4
  •  7
  •   Tom Haigh    16 年前
    $fileStr = file_get_contents('file.php');
    foreach (token_get_all($fileStr) as $token ) {
        if ($token[0] != T_COMMENT) {
            continue;
        }
        $fileStr = str_replace($token[1], '', $fileStr);
    }
    
    echo $fileStr;
    

    编辑 我意识到G·斯坦已经提出了这个建议,但我将把这个例子留在这里。

        5
  •  3
  •   ZhiJia Tang    9 年前

    更强大的版本:删除文件夹中的所有注释

    <?php
    $di = new RecursiveDirectoryIterator(__DIR__,RecursiveDirectoryIterator::SKIP_DOTS);
    $it = new RecursiveIteratorIterator($di);
    $fileArr = [];
    foreach($it as $file){
        if(pathinfo($file,PATHINFO_EXTENSION) == "php"){
            ob_start();
            echo $file;
            $file = ob_get_clean();
            $fileArr[] = $file;
        }
    }
    $arr = [T_COMMENT,T_DOC_COMMENT];
    $count = count($fileArr);
    for($i=1;$i < $count;$i++){
        $fileStr = file_get_contents($fileArr[$i]);
        foreach(token_get_all($fileStr) as $token){
            if(in_array($token[0],$arr)){
                $fileStr = str_replace($token[1],'',$fileStr);
            }            
        }
        file_put_contents($fileArr[$i],$fileStr);
    }
    
        6
  •  2
  •   Marco Demaio    11 年前

    如果你已经使用了这样的编辑器 超编辑 ,可以打开一个或多个php文件,然后使用 简单查找和替换(Ctrl+R) 使用以下Perl 正则表达式

    (?s)/\*.*\*/
    

    请注意,上面的regexp还删除了sring中的注释,即 echo "hello/*babe*/"; 这个 /*babe*/ 也会被移除。因此,如果您只有很少的文件可以删除注释,那么它可能是一个解决方案,为了确保它不会错误地替换不是注释的内容,您必须运行find&replace命令,并在每次替换内容时进行审批。

        7
  •  1
  •   Steely Wing    12 年前
    /*
    * T_ML_COMMENT does not exist in PHP 5.
    * The following three lines define it in order to
    * preserve backwards compatibility.
    *
    * The next two lines define the PHP 5 only T_DOC_COMMENT,
    * which we will mask as T_ML_COMMENT for PHP 4.
    */
    
    if (! defined('T_ML_COMMENT')) {
        define('T_ML_COMMENT', T_COMMENT);
    } else {
        define('T_DOC_COMMENT', T_ML_COMMENT);
    }
    
    /*
     * Remove all comment in $file
     */
    
    function remove_comment($file) {
        $comment_token = array(T_COMMENT, T_ML_COMMENT, T_DOC_COMMENT);
    
        $input = file_get_contents($file);
        $tokens = token_get_all($input);
        $output = '';
    
        foreach ($tokens as $token) {
            if (is_string($token)) {
                $output .= $token;
            } else {
                list($id, $text) = $token;
    
                if (in_array($id, $comment_token)) {
                    $output .= $text;
                }
            }
        }
    
        file_put_contents($file, $output);
    }
    
    /*
     * Glob recursive
     * @return ['dir/filename', ...]
     */
    
    function glob_recursive($pattern, $flags = 0) {
        $file_list = glob($pattern, $flags);
    
        $sub_dir = glob(dirname($pattern) . '/*', GLOB_ONLYDIR);
        // If sub directory exist
        if (count($sub_dir) > 0) {
            $file_list = array_merge(
                glob_recursive(dirname($pattern) . '/*/' . basename($pattern), $flags),
                $file_list
            );
        }
    
        return $file_list;
    }
    
    // Remove all comment of '*.php', include sub directory
    foreach (glob_recursive('*.php') as $file) {
        remove_comment($file);
    }
    
        8
  •  1
  •   Deele    11 年前

    对于Ajax/JSON响应,我使用下面的PHP代码,从HTML/javascript代码中删除注释,因此它会更小(我的代码获得大约15%的收益)。

    // Replace doubled spaces with single ones (ignored in HTML any way)
    $html = preg_replace('@(\s){2,}@', '\1', $html);
    // Remove single and multiline comments, tabs and newline chars
    $html = preg_replace(
        '@(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|((?<!:)//.*)|[\t\r\n]@i',
        '',
        $html
    );
    

    简短有效,但如果代码有$itty语法,则会产生意外的结果。

        9
  •  1
  •   Pawel Dubiel    8 年前

    bash解决方案:如果您想从当前目录开始从所有PHP文件中递归地删除注释,可以在终端中编写这个一行程序。(使用) temp1 存储要处理的PHP内容的文件) 请注意,这将删除所有带有注释的空白。

     find . -type f -name '*.php' | while read VAR; do php -wq $VAR > temp1  ;  cat temp1 > $VAR; done
    

    那么你应该把 TEMP1 文件之后。

    如果 PHP_BEAUTIFER 已安装 然后你就可以得到格式良好的代码而不需要注释了 具有

     find . -type f -name '*.php' | while read VAR; do php -wq $VAR > temp1; php_beautifier temp1 > temp2;  cat temp2 > $VAR; done;
    

    然后删除两个文件( TEMP1 , temp2 )

        10
  •  1
  •   Sᴀᴍ Onᴇᴌᴀ    8 年前

    运行命令 php --strip file.php 在命令提示下(即 命令提示符 ,然后浏览到 http://www.writephponline.com/phpbeautifier .

    在这里, 文件PHP 是你自己的文件。

    1

        11
  •  0
  •   Adam Davis    16 年前

    关键是,一个不那么健壮的匹配算法(例如,简单的regex)将在这里开始剥离,而它显然不应该:

    if (preg_match('#^/*' . $this->index . '#', $this->permalink_structure)) {  
    

    它可能不会影响您的代码,但最终会有人被您的脚本咬到。因此,您必须使用一个实用程序,它比您可能期望的更了解该语言。

    -亚当