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

149

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

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

Вот эта строка:

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

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

v1n_vampire
источник
18
Забавная проблема, но настоящая. Я голосую.
Voitcus
17
О, МОЙ БОГ. Сначала я скептически относился к вашему вопросу, готовый спросить, в чем проблема, но затем я попытался прокомментировать строку со строкой, содержащей «?>», И получил ее. Это должно быть добавлено в длинный список phpsadness.com
lolesque
6
Полезность такой «функции» объясняется в php.net/manual/en/language.basic-syntax.comments.php , она полезна в случае использования одной строки<?php # echo 'simple';?> .
lolesque
2
@lolesque Спасибо за эту ссылку. Хороший. Связанный, который охватывает и другие языки: wiki.theory.org/YourLanguageSucks
Саймон Форсберг,
5
@ OndraŽižka все, что он делает, это удаляет повторяющиеся теги br. регулярное выражение прекрасно работает для этого. То, что это плохо, иногда не означает, что это все время плохо.
Кип

Ответы:

124

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

В вашем коде:

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

Это заставит //комментарии работать.

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

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

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

ppeterka
источник
@ppeterka Wow, я даже не думал об этом. Спасибо.
v1n_vampire
1
Я должен был использовать этот трюк в C 2 дня назад для строки, содержащей??<
Райан Амос
2
Великий. Почему я так никогда не думаю !?
Сан
73

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

Создайте отдельную переменную для хранения вашего регулярного выражения; таким образом, вы можете просто закомментировать 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 Модификатор - он же PCRE_EXTENDED- игнорирует пробелы и переводы строк в регулярном выражении (кроме случаев , когда они происходят внутри класса символов); это позволяет добавлять пробелы для разделения проблемных символов. Чтобы исправить оба стиля комментариев:

$string = preg_replace('#<br\s* /? >(?:\s*<br\s* /? >)+#ix', '<br />', $string);
                               ^  ^             ^  ^
Разъем
источник
@Cthulhu +1 (и за ответ тоже, конечно). Также (по крайней мере, для меня) это делает регулярное выражение немного сложнее для понимания. Не очень, но если бы я увидел это регулярное выражение, я бы сказал: Хм, что происходит? Но это совершенно и совершенно субъективно.
ppeterka
1
@ppeterka Я несколько согласен, поэтому я нашел другой способ, используя xмодификатор :)
Ja͢ck
@ Джек Хорошо, я бы дал еще +1 за это, я узнал что-то новое ... Я постоянно забываю о модификаторах регулярных выражений (я редко использую их отдельно g) ...
ppeterka
@ Джек Спасибо, я узнаю что-то новое о регулярных выражениях из решения.
v1n_vampire
1
+1 за отделение регулярного выражения от предыдущей строки. Он сохраняет регулярное выражение тем же, но все же позволяет закомментировать логику.
38

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

// $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, и // или # не могут влиять на это.

Анирудх Раманатан
источник
Спасибо, так много вещей, которые я до сих пор не знаю ... Это полезно.
v1n_vampire
4
Этот пост заслуживает гораздо больше +1 ... Только для подробного объяснения.
ppeterka
15

Еще одна идея: избежать >/, если вы хотите использовать /*...*/комментарий):

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

«Ненужное» побег игнорируется механизмом регулярных выражений, но в этом случае полезно (по причинам, изложенным в других ответах).

Тим Питцкер
источник
@ppeterka: я использовал обратную косую черту вместо класса персонажей (но да, я пропустил одно вхождение. Спасибо!)
Тим Пицкер
Извините, кажется, я устал ... Я заметил второй, который был оставлен там в окружении [] ...
ppeterka
10

Зачем использовать сложные, трудно читаемые «хитрости» для обхода проблемы?

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

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

$string = preg_replace('#<br\s*/{0,1}>(?:\s*<br\s*/{0,1}>)+#i', '<br />', $string);
Stema
источник
1
+1 эта страница становится очень хорошим местом для сбора трюков с регулярными выражениями, чтобы держать их в голове.
ppeterka
1
@ppeterka, я бы назвал все остальные ответы «хитростями», но мой ответ - использовать длинную версию квантификатора, а не ярлык.
Stema
3
Без обид, только то, что в моем словаре вместо длинного и более удобного синтаксического сахара используется более длинная версия выражения, тоже считается трюком ...
ppeterka
8

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

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

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

  • Используйте собственнические квантификаторы : #(<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

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

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

$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

CSᵠ
источник