自动从PHP代码中删除评论的最佳方法

什么是从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(); ?> 

(虽然如果空行留在注释被删除,那就不行了)。

这可能是不可能的,因为需要保留embedded式的HTML – 这是什么绊了谷歌上出现的东西。

我会使用分词器 。 这是我的解决scheme。 它应该适用于PHP 4和PHP 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; 

如何使用PHP -W生成一个文件被剥夺了评论和空白,然后使用美化PHP_Beautifier重新格式化的可读性?

下面是上面发布的函数,修改后recursion地删除目录及其所有子目录中所有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"); 
 $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; 

编辑我意识到Ionut G. Stan已经提出了这个build议,但我将在这里留下这个例子

更强大的版本:删除文件夹中的所有评论

 <?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); } 

如果你已经使用了像UltraEdit这样的编辑器,你可以打开一个或多个PHP文件,然后使用一个简单的Find&Replace(CTRL + R)和下面的Perl regexp

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

注意上面的正则expression式也删除了一个sring里面的注释,例如echo "hello/*babe*/"; /*babe*/也将被删除。 因此,如果你有很less的文件要删除注释,那么这个解决scheme可能是一个解决scheme,为了绝对确保它不会错误地replace那些不是注释的东西,你将不得不运行“查找和replace”命令,并且每次批准replace内容。

 /* * 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); } 

对于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语法,可能会产生意想不到的结果。

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

在这里, file.php是你自己的文件。

1

这个问题的关键是一个不太可靠的匹配algorithm(例如简单的正则expression式)将会在这里显然不应该开始剥离:

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

它可能不会影响你的代码,但最终有人会得到你的脚本。 所以你将不得不使用一种比你所期望的更能理解语言的工具。

-亚当

Bash解决scheme:如果你想从当前目录开始,从所有PHP文件中recursion地删除注释,你可以在terminal中写入这一行。 (它使用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; 

然后删除两个文件( temp1temp2