从PHP文件中删除评论的最佳方法是什么?
我想做类似strip-whitespace()的事情 - 但它也不应该删除换行符。
EG:
我想要这个:
<?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上出现的东西。
答案 0 :(得分:51)
我会使用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;
答案 1 :(得分:39)
如何使用php -w生成一个剥离了注释和空格的文件,然后使用像PHP_Beautifier这样的美化器来重新格式化以便于阅读?
答案 2 :(得分:8)
这是上面发布的函数,修改为递归删除目录及其所有子目录中所有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");
答案 3 :(得分:7)
$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已经提出了这个建议,但我会在这里留下这个例子
答案 4 :(得分:3)
更强大的版本:删除文件夹中的所有评论
<?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);
}
答案 5 :(得分:2)
如果您已使用 UltraEdit 等编辑器,则可以打开一个或多个PHP文件,然后使用简单查找和替换(CTRL + R)以下Perl 正则表达式
(?s)/\*.*\*/
请注意上面的正则表达式也会删除sring中的注释,即在echo "hello/*babe*/";
/*babe*/
中也会删除{{1}}。因此,如果您只有少量文件可以删除注释,那么它可能是一个解决方案,以便绝对确定它不会错误地替换不是注释的内容,您必须运行“查找和替换”命令并在每次获取时获得批准替换。
答案 6 :(得分:1)
/*
* 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);
}
答案 7 :(得分:1)
对于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语法,则会产生意外结果。
答案 8 :(得分:1)
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
)
答案 9 :(得分:1)
在命令提示符下运行命令php --strip file.php
(即 cmd.exe ),然后浏览到 http://www.writephponline.com/phpbeautifier 。
此处, file.php 是您自己的文件。
答案 10 :(得分:0)
问题是,一个不太健壮的匹配算法(例如简单的正则表达式)将在这里开始剥离,但显然不应该:
if (preg_match('#^/*' . $this->index . '#', $this->permalink_structure)) {
它可能不会影响您的代码,但最终会有人通过您的脚本获得一些代价。因此,您必须使用能够理解更多语言的实用程序。
- 亚当
答案 11 :(得分:0)
在2019年可以像这样
<?php
/* hi there !!!
here are the comments */
//another try
echo removecomments('index.php');
/* hi there !!!
here are the comments */
//another try
function removecomments($f){
$w=Array(';','{','}');
$ts = token_get_all(php_strip_whitespace($f));
$s='';
foreach($ts as $t){
if(is_array($t)){
$s .=$t[1];
}else{
$s .=$t;
if( in_array($t,$w) ) $s.=chr(13).chr(10);
}
}
return $s;
}
?>
如果要查看结果,请先在xampp中运行它,然后会得到一个空白页,但是如果右键单击并单击查看源代码,则会得到php脚本。它正在加载自身,并且正在删除所有注释,并且标签。 我也更喜欢这种解决方案,因为我使用它来加快我的框架一个文件引擎“ m.php”的速度,并且在php_strip_whitespace之后,我观察到的所有没有此脚本的资源都是最慢的:我做了10个基准测试,然后计算了数学平均值(我认为php 7正在解析时还原丢失的cr_lf或在丢失时需要一段时间)
答案 12 :(得分:0)
php -w
或php_strip_whitespace($filename);
答案 13 :(得分:0)
在接受答案之后,我也需要保留文件的行号,因此这是接受答案的一种变体:
/**
* Removes the php comments from the given valid php string, and returns the result.
*
* Note: a valid php string must start with <?php.
*
* If the preserveWhiteSpace option is true, it will replace the comments with some whitespaces, so that
* the line numbers are preserved.
*
*
* @param string $str
* @param bool $preserveWhiteSpace
* @return string
*/
function removePhpComments(string $str, bool $preserveWhiteSpace = true): string
{
$commentTokens = [
\T_COMMENT,
\T_DOC_COMMENT,
];
$tokens = token_get_all($str);
if (true === $preserveWhiteSpace) {
$lines = explode(PHP_EOL, $str);
}
$s = '';
foreach ($tokens as $token) {
if (is_array($token)) {
if (in_array($token[0], $commentTokens)) {
if (true === $preserveWhiteSpace) {
$comment = $token[1];
$lineNb = $token[2];
$firstLine = $lines[$lineNb - 1];
$p = explode(PHP_EOL, $comment);
$nbLineComments = count($p);
if ($nbLineComments < 1) {
$nbLineComments = 1;
}
$firstCommentLine = array_shift($p);
$isStandAlone = (trim($firstLine) === trim($firstCommentLine));
if (false === $isStandAlone) {
if (2 === $nbLineComments) {
$s .= PHP_EOL;
}
continue; // just remove inline comments
}
// stand alone case
$s .= str_repeat(PHP_EOL, $nbLineComments - 1);
}
continue;
}
$token = $token[1];
}
$s .= $token;
}
return $s;
}
注意:这是针对php 7+(我不关心与旧php版本的向后兼容性)。