(php) regex, чтобы удалить комментарии, но игнорировать вхождения внутри строк - PullRequest
0 голосов
/ 19 марта 2010

Я пишу комментарий-стриптизер и пытаюсь приспособиться для всех нужд здесь. У меня есть приведенный ниже стек кода, который удаляет почти все комментарии, но на самом деле он заходит слишком далеко. Много времени было потрачено на тестирование и исследование шаблонов регулярных выражений, но я не утверждаю, что они являются лучшими в каждом.

Моя проблема в том, что у меня также есть ситуация, когда у меня есть «комментарии PHP» (которые на самом деле не являются комментариями »в стандартном коде или даже в строках PHP, которые я на самом деле не хочу удалять.

Пример:

<?php $Var = "Blah blah //this must not comment"; // this must comment. ?>

То, что в итоге происходит, это то, что оно религиозно выходит из себя, что нормально, но оставляет определенные проблемы:

<?php  $Var = "Blah blah  ?>

Также:

также вызовет проблемы, так как комментарий удаляет остальную часть строки, включая окончание?>

Видите проблему? Так вот что мне нужно ...

  • Символы комментария внутри '' или "" должны игнорироваться
  • Комментарии PHP в той же строке, где используются двойные слэши, должны удалять, возможно, только сам комментарий или удалять весь кодовый блок php.

Вот шаблоны, которые я использую в данный момент, не стесняйтесь сказать мне, могу ли я улучшить мои существующие шаблоны? :)

$CompressedData = $OriginalData;
$CompressedData = preg_replace('!/\*.*?\*/!s', '', $CompressedData);  // removes /* comments */
$CompressedData = preg_replace('!//.*?\n!', '', $CompressedData); // removes //comments
$CompressedData = preg_replace('!#.*?\n!', '', $CompressedData); // removes # comments
$CompressedData = preg_replace('/<!--(.*?)-->/', '', $CompressedData); // removes HTML comments

Буду очень признателен за любую помощь, которую вы мне можете оказать! :)

Ответы [ 4 ]

4 голосов
/ 19 марта 2010

Если вы хотите проанализировать PHP, вы можете использовать token_get_all, чтобы получить токены данного PHP-кода. Затем вам просто нужно перебрать токены, удалить токены комментариев и собрать остальные вместе.

Но вам понадобится отдельная процедура для комментариев HTML, предпочтительно реальный парсер (например, DOMDocument предоставляет DOMDocument::loadHTML).

3 голосов
/ 19 марта 2010

Сначала вы должны тщательно подумать, действительно ли вы хотите это сделать. Хотя то, что вы делаете, может показаться простым, в худшем случае это становится чрезвычайно сложной задачей (решить с помощью нескольких регулярных выражений). Позвольте мне проиллюстрировать лишь несколько проблем, с которыми вы можете столкнуться, пытаясь убрать комментарии HTML и PHP из файла.

Вы не можете разметать комментарии HTML, потому что у вас может быть PHP внутри комментариев HTML, например:

<!-- HTML comment <?php echo 'Actual PHP'; ?> -->

Вы не можете просто отдельно разобраться с вещами внутри тегов <?php и ?>, так как завершающий тег ?> может быть внутри строк или даже комментариев, например:

<?php /* ?> This is still a PHP comment <?php */ ?>

Давайте не будем забывать, что ?> фактически завершает PHP, если ему предшествует однострочный комментарий. Например:

<?php // ?> This is not a PHP comment <?php ?>

Конечно, как вы уже иллюстрировали, будет много проблем с индикаторами комментариев внутри строк. Разбирать строки, чтобы игнорировать их, тоже не так просто, так как вы должны помнить, что кавычки можно экранировать. Как:

<?php
$foo = ' /* // None of these start a comment ';
$bar = ' \' // Remember escaped quotes ';
$orz = " ' \" \' /* // Still not a comment ";
?>

Порядок синтаксического анализа также вызовет у вас головную боль. Вы не можете просто выбрать сначала анализ однострочных комментариев или многострочных комментариев. Они оба должны быть проанализированы одновременно (т.е. в порядке их появления в документе). В противном случае вы можете получить неработающий код. Позвольте мне проиллюстрировать:

<?php
/* // Multiline comment */
// /* Single Line comment
$omg = 'This is not in a comment */';
?>

Если вы сначала анализируете многострочные комментарии, второй / * съест часть строки, разрушающую код. Если вы сначала проанализируете однострочные комментарии, вы в конечном итоге съедите первый * /, что также уничтожит код.

Как видите, существует множество сложных сценариев, которые вам необходимо учитывать, если вы собираетесь решить свою проблему с помощью регулярных выражений. Единственное правильное решение - использовать какой-то синтаксический анализатор PHP, например token_get_all(), для токенизации всего исходного кода, удаления токенов комментариев и перестройки файла. Что, боюсь, тоже не совсем просто. Это также не поможет с комментариями HTML, так как HTML остается нетронутым. Вы также не можете использовать парсеры XML для получения комментариев HTML, потому что HTML редко формируется с помощью PHP.

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

0 голосов
/ 06 октября 2017

попробуйте

private function removeComments( $content ){
    $content = preg_replace( "!/\*.*?\*/!s" , '', $content );
    $content = preg_replace( "/\n\s*\n/" , "\n", $content );    
    $content = preg_replace( '#^\s*//.+$#m' , "", $content );
    $content = preg_replace( '![\s\t]//.*?\n!' , "\n", $content );
    $content = preg_replace( '/<\!--.*-->/' , "\n", $content );
    return $content;
}
0 голосов
/ 19 марта 2010

Один из способов сделать это в REGEX - использовать одно составное выражение и preg_replace_callback.

Я собирался опубликовать плохой пример, но лучше всего посмотреть исходный код на порт PHP сценария упаковщика JS Дина Эдвардса - вы должны увидеть общую идею.

http://joliclic.free.fr/php/javascript-packer/en/

...