Лучший способ автоматического удаления комментариев из 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(); ?> 

(Хотя, если пустые строки остаются там, где комментарии удалены, это не будет нормально).

Это может быть невозможно, из-за требования сохранить встроенный html – вот что расстроило то, что появилось в Google.

Я бы использовал токенизатор . Вот мое решение. Он должен работать как на 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; 

Как насчет использования php -w для генерации файла, лишенного комментариев и пробелов, а затем с помощью beautifier, такого как PHP_Beautifier, для переформатирования для удобочитаемости?

Вот функция, опубликованная выше, измененная для рекурсивного удаления всех комментариев из всех 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; 

Я понял, что Ионут Г. Стэн уже предложил это, но я оставлю здесь пример

версия более мощная: удалите все комментарии в папке

 <?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)/\*.*\*/ 

Остерегайтесь вышеуказанного regexp удаляет также комментарии внутри sring, то есть в echo "hello/*babe*/"; /*babe*/ будет удален. Следовательно, это может быть решение, если у вас мало файлов для удаления комментариев, чтобы быть абсолютно уверенным, что он не ошибочно заменяет то, что не является комментарием, который вам нужно будет выполнять командой Find & 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.

Запустите команду php --strip file.php в командной строке (например cmd.exe ), затем перейдите на php --strip file.php http://www.writephponline.com/phpbeautifier .

Здесь file.php является вашим собственным файлом.

1

Уловка заключается в том, что менее надежный алгоритм совпадения (например, простого регулярного выражения) начнет зачищать здесь, когда он явно не должен:

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

Это может не повлиять на ваш код, но в конце концов кто-то получит ваш скрипт. Поэтому вам придется использовать утилиту, которая понимает больше языка, чем вы могли бы ожидать.

-Адам

Решение Bash: если вы хотите удалить рекурсивные комментарии из всех файлов PHP, начиная с текущего каталога, вы можете записать в терминал этот однострочный. (он использует файл temp1 для хранения содержимого PHP для обработки). Обратите внимание, что это temp1 все пробелы с комментариями.

  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 )