Перетворити закритий тег PHP в коментар


149

Один з рядків мого сценарію містить тег закриття PHP всередині рядка. При нормальній роботі це не викликає проблем, але мені потрібно прокоментувати рядок.

Я спробував прокоментувати цю лінію //, /* */і , #але жоден з них працює, синтаксичний аналізатор не вважає закриває тегом , щоб бути фактичним закриває тегом.

Ось рядок, про який йдеться:

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

Що я можу зробити, щоб прокоментувати вищевказаний рядок?


18
Кумедна проблема, але реальна. Я голосую.
Voitcus

17
О БОЖЕ МІЙ. Спочатку я скептично ставився до вашого запитання, готовий запитати, у чому проблема, але потім я спробував прокоментувати рядок із рядком, що містить "?>", І я його отримав. До цього слід додати довгий список phpsadness.com
lolesque

6
Корисність такої "функції" пояснюється в php.net/manual/en/language.basic-syntax.comments.php , вона корисна у випадку з одним лайнером <?php # echo 'simple';?>.
лолеск

2
@lolesque Дякую за це посилання Хороший. Пов’язаний, який охоплює й інші мови: wiki.theory.org/YourLanguageSucks
Simon Forsberg

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 Нічого собі, я навіть не думала про це. Дякую.
v1n_vampire

1
Мені довелося використовувати цей трюк у С 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 (і для відповіді теж, звичайно). Також (принаймні, для мене) це робить regexp дещо складнішим для розуміння. Не на багато, але якби я побачив цей вираз, я б сказав: Хммм, що відбувається? Але це прямо і абсолютно суб'єктивно.
ppeterka

1
@ppeterka Я дещо згоден, тому я знайшов інший спосіб, використовуючи xмодифікатор :)
Ja͢ck

@Jack Nice, я би дав ще +1 за це, я дізнався щось нове ... Я постійно забуваю про модифікатори g
регексу

@Jack Дякую, я дізнаюся нові речі про регекс із рішення.
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);

1
+1 ця сторінка починає бути дуже хорошим місцем для збору трюків з регулярними виразками, які слід тримати в задній частині розуму.
ppeterka

1
@ppeterka, я б фактично назвав усі інші відповіді "хитрощами", але моя відповідь - це лише використання довгої версії квантора, а не ярлик.
стема

3
Без образи, лише те, що в моєму словнику, використовуючи довгу версію виразу замість коротшого, зручнішого синтаксичного цукру, теж вважається хитрістю ...
ppeterka

8

Ще кілька способів, які варто додати до книги фокусів RegEx :

По-перше, ви можете компактний ваш RegEx: /(<br\s*/?>)+/iі замінити на <br />(не потрібно обтяжувати RegExP lookaheads), і ви завжди будете в кінцевому підсумку з обраним вами розривом XHMTL.

Інші способи змінити ваш RegEx, щоб він не вимикав */кінцевий коментар чи ?>кінцевий сценарій:

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

Демонстраційні демонстрації: http://codepad.viper-7.com/YjqUbi

А оскільки ми нахилилися до нав'язливої ​​поведінки, найшвидший RegEx, який також обходить проблему коментування: пояснив демо#(<br\s*+/?+>)++#i


Що стосується коментування в складних ситуаціях

Якщо ви не можете змінити код або вже використовували багаторядковий коментар і:

1. Використовуйте заразdoc :

    $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. Перехід до коду за допомогою 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.