Преобразование закрывающего тега PHP в комментарий

Одна из строк в моем script содержит закрывающий тег PHP внутри строки. При нормальной работе это не вызывает проблемы, но мне нужно прокомментировать строку.

Я попытался прокомментировать эту строку с //, /* */ и #, но ни один из них не работает, парсер считает закрывающий тег фактическим закрывающим тегом.

Вот строка, о которой идет речь:

$string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i', '<br />', $string);
//                              ^^             ^^

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

Ответ 1

Используйте трюк: объедините строку из двух частей. Таким образом, закрывающий тег разрезается на два и больше не является допустимым закрывающим тегом. '?>' --> '?'.'>'

В вашем коде:

$string = preg_replace('#<br\s*/?'.'>(?:\s*<br\s*/?'.'>)+#i', '<br />', $string);

Это сделает комментарии //.

Для комментариев /* */ для работы вам также потребуется разбить последовательность */:

$string = preg_replace('#<br\s*'.'/?'.'>(?:\s*<br\s*'.'/?'.'>)+#i', '<br />', $string);

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

Ответ 2

Самый простой способ

Создайте отдельную переменную, чтобы сохранить регулярное выражение; таким образом вы можете просто прокомментировать инструкцию preg_replace():

$re = '#<br\s*/?>(?:\s*<br\s*/?>)+#i';
// $string = preg_replace($re, '<br />', $string);

Исправить использование классов символов

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

$string = preg_replace('#<br\s*/?[>](?:\s*<br\s*/?[>])+#i', '<br />', $string);
                                 ^ ^              ^ ^

Чтобы исправить комментарии блока, вы можете применить его к /:

$string = preg_replace('#<br\s*[/]?>(?:\s*<br\s*[/]?>)+#i', '<br />', $string);
                               ^ ^              ^ ^

Чтобы исправить оба стиля комментариев, вы можете поместить / и > в свой собственный класс символов.

Исправить с помощью модификатора /x

x modifier - aka PCRE_EXTENDED - игнорирует пробелы и символы новой строки в регулярном выражении (за исключением случаев, когда они встречаются внутри класс символов); это позволяет добавлять пробелы для разделения проблемных символов. Чтобы исправить оба стиля комментариев:

$string = preg_replace('#<br\s* /? >(?:\s*<br\s* /? >)+#ix', '<br />', $string);
                               ^  ^             ^  ^

Ответ 3

Почему ваши попытки не сработали:

// $string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i',...
                                   ^ doesn't work due to ?> ending php

/* $string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i',... */
                                 ^ doesn't work due to */ closing comment

Что работает:

/* $string = preg_replace('#<br\s*[/]?>(?:\s*<br\s*[/]?>)+#i',... */
                                  ^ ^              ^ ^
// $string = preg_replace('#<br\s*/?[>](?:\s*<br\s*/?[>])+#i',...
                                    ^ ^              ^ ^

Далее...

После вышесказанного вы можете использовать /*, чтобы прокомментировать строку. Если вы оставите ?> неповрежденным, // не может комментировать всю строку. Текст, следующий за ?>, может быть html, который вне элемента управления интерпретатора PHP, так что это не сработает.

От документация:

"Однострочные" стили комментариев комментируют только конец строки или текущий блок кода PHP, в зависимости от того, что наступит раньше. Это значит, что HTML-код после //...? > Или #...? > Будет напечатан:? > Разрывается режима PHP и возвращается в режим HTML, а//или # не могут влиять что.

Ответ 4

Другая идея: Escape >/, если вы хотите использовать комментарий /*...*/):

$string = preg_replace('#<br\s*\/?\>(?:\s*<br\s*\/?\>)+#i', '<br />', $string);

"ненужный" escape игнорируется движком регулярных выражений, но полезен в этом случае (по причинам, изложенным в других ответах).

Ответ 5

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

? - это просто ярлык квантификатора для удобства, поэтому

Просто используйте длинную версию квантификатора {0,1}, значит "минимум 0 максимум 1 вхождение":

$string = preg_replace('#<br\s*/{0,1}>(?:\s*<br\s*/{0,1}>)+#i', '<br />', $string);

Ответ 6

Несколько других способов добавить в книгу трюков RegEx:

Сначала вы можете сжать свой RegEx до: /(<br\s*/?>)+/i и заменить на <br /> (нет необходимости обременять RegExP с помощью lookaheads), и вы всегда будете в конечном итоге с выбранным вами перерывом строки XHMTL.

Другие способы изменения вашего RegEx, чтобы он не отключил окончательный комментарий */ или ?> end script:

  • Используйте притяжательные квантификаторы: #(<br\s*+/?+>)+#i - которые в основном означают для \s*+, если вы нашли пробельные совпадения столько, сколько их есть и сохраните, а для /?+ если вы нашли косую черту!
  • Включить \s* и /* в группы захвата = > #(<br(\s*)(/?)>)+#i

Живые демонстрации: http://codepad.viper-7.com/YjqUbi

И так как мы склонялись к притяжательному поведению, самый быстрый RegEx, который также обходит проблему комментариев: #(<br\s*+/?+>)++#i объяснил демо


Что касается комментирования в сложных ситуациях

Если вы не можете изменить код или уже использовали многострочный комментарий и:

1. Используйте nowdoc:

    $string='Hello<br>World<br><br />World<br><br><br>Word!';
    <<<'comment'
    $string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
comment;

Живой код: http://codepad.viper-7.com/22uOtV

Примечание: a nowdoc похож на heredoc, но он не анализирует содержимое и должен иметь его начальный разделитель, заключенный в ' одинарные кавычки ' (обратите внимание, что окончательный разделитель не может быть идентифицирован, за ним следует ; и новая строка!)

2. Перепрыгните через код с помощью goto:

$string='Hello<br>World<br><br />World<br><br><br>Word!';
goto landing;
$string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
landing:

Пример в реальном времени: http://codepad.viper-7.com/UfqrIQ

3. Перепрыгните через код с помощью if(false) или if(0):

$string='Hello<br>World<br><br />World<br><br><br>Word!';
if(0){
$string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
}

Тест: http://codepad.viper-7.com/wDg5H5