Najlepszy sposób na automatyczne usuwanie komentarzy z kodu PHP

Jaki jest najlepszy sposób na usunięcie komentarzy z pliku PHP?

Chcę zrobić coś podobnego do strip-whitespace() - ale nie powinno to również usuwać podziałów linii.

EG:

Chcę tego:

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

Zostać:

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

(chociaż jeśli puste linie pozostaną tam, gdzie komentarze są usuwane, nie byłoby to w porządku).

Być może nie jest to możliwe, ze względu na wymóg zachowania osadzonego html - to co pojawiły się w google.

Author: Coral Doe, 2009-02-02

14 answers

Użyłbym tokenizera . Oto moje rozwiązanie. Powinno działać zarówno na PHP 4 jak i 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;
 61
Author: Ionuț G. Stan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-13 09:56:49

Co powiesz na użycie PHP-w do wygenerowania pliku pozbawionego komentarzy i spacji, a następnie użycie piękniejszego jak PHP_Beautifier do sformatowania dla czytelności?

 45
Author: Paul Dixon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-02 17:02:22
$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;

Edytuj Zdałem sobie sprawę, że Ionut G. Stan już to zasugerował, ale zostawię przykład tutaj

 9
Author: Tom Haigh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-02 17:06:17

Oto funkcja zamieszczona powyżej, zmodyfikowana tak, aby rekurencyjnie usuwać wszystkie komentarze ze wszystkich plików php w katalogu i wszystkich jego podkatalogach:

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");
 9
Author: John Tyler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-15 10:49:31

Wersja mocniejsza: usuń wszystkie komentarze w folderze

<?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);
}
 4
Author: ZhiJia Tang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-07 11:17:48

Jeśli używasz już edytora, takiego jak UltraEdit, możesz otworzyć jeden lub wiele plików PHP, a następnie użyć simple Find&Replace (CTRL+R) z następującym Perl regexp

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

Uwaga powyższe regexp usuwa również komentarze wewnątrz sring, tzn. w echo "hello/*babe*/"; /*babe*/ również zostaną usunięte. Dlatego może to być rozwiązanie, jeśli masz kilka plików do usunięcia komentarzy, aby mieć absolutną pewność, że nie zastępuje on nieprawidłowo czegoś, co nie jest komentarzem, który byś musisz uruchomić polecenie Znajdź i Zamień i zatwierdzać za każdym razem, co jest zastępowane.

 2
Author: Marco Demaio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-25 18:26:30

Rozwiązanie Bash: jeśli chcesz usunąć rekurencyjnie komentarze ze wszystkich plików PHP począwszy od bieżącego katalogu, możesz napisać w terminalu ten jeden-liner. ( używa pliku temp1 do przechowywania zawartości PHP do przetwarzania ) zauważ, że spowoduje to usunięcie wszystkich białych spacji z komentarzami.

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

Następnie należy usunąć temp1 plik po.

Jeśli php_beautifer jest zainstalowany to możesz uzyskać ładnie sformatowany kod bez komentarzy za pomocą

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

Wtedy usuń dwa pliki ( temp1, temp2 )

 2
Author: Pawel Dubiel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-13 12:30:00
/*
* 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);
}
 1
Author: Steely Wing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-08 14:39:20

Dla odpowiedzi ajax / json, używam następującego kodu PHP, aby usunąć komentarze z kodu HTML / JavaScript, więc byłby mniejszy(około 15% zysku dla mojego kodu).

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

Krótki i skuteczny, ale może przynieść nieoczekiwane rezultaty, jeśli twój kod ma składnię $itty.

 1
Author: Deele,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-18 17:39:02

Uruchom polecenie php --strip file.php w wierszu polecenia (np. cmd.exe ), Następnie przejdź do http://www.writephponline.com/phpbeautifier.

Tutaj, Plik.php jest twoim własnym plikiem.

1

 1
Author: Robi Parvez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-18 19:53:58

W 2019 roku może działać tak

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

?>

Jeśli chcesz zobaczyć wyniki po prostu uruchom go najpierw w xampp następnie otrzymasz pustą stronę, ale jeśli klikniesz prawym przyciskiem myszy i klikniesz na view source otrzymasz skrypt php .. ładuje się i usuwa wszystkie komentarze, a także karty. ja też wolę to rozwiązanie, bo używam go do przyspieszenia mojego frameworka one file engine "m.php" a po php_strip_whitespace wszystkie źródła bez tego skryptu obserwuję są najwolniejsze :zrobiłem 10 benchmarków potem Oblicz średnią matematyczną (myślę, że php 7 przywraca brakujące cr_lf podczas parsowania lub zajmuje trochę czasu, gdy brakuje tych)

 1
Author: Constantin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-20 10:52:45

php -w LUB php_strip_whitespace($filename);

Dokumentacja

 1
Author: Gam Sengie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-11 10:33:57

Haczyk polega na tym, że mniej solidny algorytm dopasowywania (na przykład proste wyrażenia regularne) zacznie się tutaj rozbierać, gdy wyraźnie nie powinien:

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

Może to nie wpłynąć na Twój kod, ale w końcu ktoś zostanie ugryziony przez twój skrypt. Musisz więc użyć narzędzia, które rozumie więcej języka, niż możesz się spodziewać.

- Adam

 0
Author: Adam Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-02 16:59:21

Po zaakceptowanej odpowiedzi, musiałem również zachować numery linii pliku, więc oto odmiana zaakceptowanej odpowiedzi:

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

Uwaga: To jest dla php 7+ (nie dbałem o kompatybilność wsteczną ze starszymi wersjami php).

 0
Author: ling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-23 09:54:47