Konvertieren Sie das PHP-Abschluss-Tag in einen Kommentar


149

Eine der Zeilen in meinem Skript enthält ein PHP-Abschluss-Tag in einer Zeichenfolge. Im normalen Betrieb verursacht dies kein Problem, aber ich muss die Zeile auskommentieren.

Ich habe versucht , mit dieser Zeile auszukommen //, /* */und #aber keiner von ihnen zu arbeiten, hält die Parser - Tag einen tatsächlicher End - Tag zu sein , zu schließen.

Hier ist die fragliche Zeile:

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

Was kann ich tun, um die obige Zeile zu kommentieren?


18
Lustiges Problem, aber echt. Ich stimme ab.
Voitcus

17
OH MEIN GOTT. Zuerst war ich skeptisch gegenüber Ihrer Frage und bereit zu fragen, was das Problem war, aber dann habe ich versucht, eine Zeile mit einer Zeichenfolge zu kommentieren, die '?>' Enthält, und ich habe sie verstanden. Dies sollte der langen Liste von phpsadness.com
lolesque

6
Die Nützlichkeit einer solchen "Funktion" wird in php.net/manual/en/language.basic-syntax.comments.php erläutert. Sie ist bei Einzeilern nützlich <?php # echo 'simple';?>.
Lolesque

2
@lolesque Danke für diesen Link. Ein guter. Eine verwandte, die auch andere Sprachen abdeckt
Simon Forsberg

5
@ OndraŽižka alles, was er tut, ist, wiederholte br-Tags zu entfernen. Ein Regex funktioniert gut dafür. Nur weil es manchmal schlecht ist, heißt das nicht, dass es die ganze Zeit schlecht ist.
Kip

Antworten:


124

Verwenden Sie einen Trick: Verketten Sie die Zeichenfolge aus zwei Teilen. Auf diese Weise wird das schließende Tag in zwei Teile geteilt und ist kein gültiges schließendes Tag mehr.'?>' --> '?'.'>'

In Ihrem Code:

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

Dadurch //funktionieren Kommentare.

Damit /* */Kommentare funktionieren, müssen Sie auch die */Sequenz aufteilen :

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

Denken Sie manchmal daran, dass das Ganze mehr ist als die Summe seiner Teile - aber gierig zu sein ist schlecht, es gibt Zeiten, in denen Sie besser weniger haben . :) :)


@ppeterka Wow, darüber habe ich gar nicht nachgedacht. Danke dir.
v1n_vampire

1
Ich musste diesen Trick in C vor 2 Tagen für eine Zeichenfolge verwenden, die??<
Ryan Amos

2
Tolle Sache. Warum denke ich nie so?
San

73

Der einfachste Weg

Erstellen Sie eine separate Variable für Ihren regulären Ausdruck. Auf diese Weise können Sie die preg_replace()Aussage einfach auskommentieren :

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

Fix mit Zeichenklassen

Um Zeilenkommentare zu korrigieren, können Sie sich trennen, ?>indem Sie >eine Zeichenklasse wie folgt eingeben :

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

Um Blockkommentare zu korrigieren, können Sie sie anwenden auf /:

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

Um beiden Kommentarstile zu beheben, können Sie setzen / und > ihre eigenen Charakterklasse in.

Fix mit dem /xModifikator

Der x Modifikator - auch bekannt als PCRE_EXTENDED- ignoriert Leerzeichen und Zeilenumbrüche in einem regulären Ausdruck (außer wenn sie innerhalb einer Zeichenklasse vorkommen). Dies ermöglicht das Hinzufügen von Leerzeichen, um die problematischen Zeichen zu trennen. So korrigieren Sie beide Kommentarstile:

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

@Cthulhu +1 (und natürlich auch für die Antwort). Auch (zumindest für mich) macht es das Regexp etwas schwieriger zu verstehen. Nicht viel, aber wenn ich diesen regulären Ausdruck sehen würde, würde ich sagen: Hmmm, was ist los? Aber das ist geradezu und total subjektiv.
ppeterka

1
@ppeterka Ich stimme etwas zu, also habe ich einen anderen Weg gefunden, indem ich den xModifikator verwendet habe :)
Ja͢ck

@ Jack Nice, ich würde noch eine +1 dafür geben, ich habe etwas Neues gelernt ... Ich vergesse immer wieder die Regex-Modifikatoren (ich benutze sie selten außer g) ...
ppeterka

@ Jack Danke, ich lerne neue Dinge über Regex aus der Lösung.
v1n_vampire

1
+1 zum Trennen des regulären Ausdrucks in eine frühere Zeile. Der reguläre Ausdruck bleibt gleich, die Logik kann jedoch auskommentiert werden.

38

Warum Ihre Versuche nicht funktionierten:

// $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

Was funktioniert:

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

Des Weiteren...

Nach dem oben Gesagten sollten Sie in der Lage sein /*, die Zeile zu kommentieren. Wenn Sie das ?>intakt lassen, //können Sie möglicherweise nicht eine ganze Zeile auskommentieren. Der folgende Text ?>könnte HTML sein, der außerhalb der Kontrolle des PHP-Interpreters liegt, sodass dies nicht funktioniert.

Aus der Dokumentation:

Die "einzeiligen" Kommentarstile kommentieren nur das Zeilenende oder den aktuellen PHP-Codeblock, je nachdem, was zuerst eintritt. Dies bedeutet, dass HTML-Code nach // ...?> Oder # ...?> Gedruckt wird :?> Bricht aus dem PHP-Modus aus und kehrt in den HTML-Modus zurück, und // oder # können dies nicht beeinflussen.


Vielen Dank, so viele Dinge, die ich immer noch nicht weiß ... Es ist hilfreich.
v1n_vampire

4
Dieser Beitrag würde weit mehr + 1s verdienen ... Nur für die gründliche Erklärung.
ppeterka

15

Eine andere Idee: Escape the >(und die /, wenn Sie einen /*...*/Kommentar verwenden möchten ):

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

Ein "unnötiges" Escape wird von der Regex-Engine ignoriert, ist jedoch in diesem Fall nützlich (aus Gründen, die in den anderen Antworten aufgeführt sind).


@ppeterka: Ich habe einen Backslash anstelle einer Zeichenklasse verwendet (aber ja, ich habe ein Vorkommen verpasst. Danke!)
Tim Pietzcker

Tut mir leid, ich bin anscheinend müde ... Ich bemerkte den zweiten, der dort umgeben von [] ...
ppeterka

10

Warum komplizierte, schwer zu lesende "Tricks" verwenden, um das Problem zu umgehen?

? ist nur eine Abkürzung für den Quantifizierer

Verwenden Sie einfach die lange Version des Quantifizierers{0,1} , was "Minimum 0 Maximum 1 Vorkommen" bedeutet:

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

1
+1 Diese Seite ist ein sehr guter Ort, um Regex-Tricks zu sammeln und im Hinterkopf zu behalten.
ppeterka

1
@ppeterka, ich würde eigentlich alle anderen Antworten "Tricks" nennen, aber meine Antwort verwendet nur die lange Version des Quantifizierers und nicht die Verknüpfung.
Stema

3
Nichts für ungut, nur das in meinem Wörterbuch, wenn man die lange Version eines Ausdrucks anstelle des kürzeren, bequemeren syntaktischen Zuckers verwendet, zählt man auch als Trick ...
ppeterka

8

Einige andere Möglichkeiten, die es wert sind, in das RegEx-Trickbuch aufgenommen zu werden :

Zuerst können Sie Ihren RegEx komprimieren, um: /(<br\s*/?>)+/iund durch zu ersetzen <br />(Sie müssen den RegExP nicht mit Lookaheads belasten), und Sie erhalten immer den von Ihnen gewählten XHMTL-Zeilenumbruch.

Andere Möglichkeiten, Ihr RegEx so zu ändern, dass es keinen */Endkommentar oder Endskript auslöst ?>:

  • Verwenden Sie besitzergreifende Quantifizierer : #(<br\s*+/?+>)+#i- was im Grunde bedeutet, \s*+wenn Sie festgestellt haben, dass Leerzeichen mit so vielen übereinstimmen, wie es gibt, und behalten Sie es, und /?+wenn Sie einen Schrägstrich gefunden haben, behalten Sie es!
  • Einschließen \s*und /*in Erfassungsgruppen =>#(<br(\s*)(/?)>)+#i

Live-Demos: http://codepad.viper-7.com/YjqUbi

Und da wir uns auf das besitzergreifende Verhalten gestützt haben, ist das schnellste RegEx, das auch das Kommentarproblem umgeht, die erklärte Demo#(<br\s*+/?+>)++#i


Wie zum Kommentieren in schwierigen Situationen

Wenn Sie den Code nicht ändern können oder bereits einen mehrzeiligen Kommentar verwendet haben und:

1. Verwenden Sie einen Nowdoc :

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

Live-Code: http://codepad.viper-7.com/22uOtV

Hinweis: a Nowdoc ähnelt einem heredoc aber nicht den Inhalt analysieren und hat es zu haben ist Anlaßtrennzeichen in geschlossenen 'Apostrophe '( beachten Sie, dass die Endbegrenzer kann nicht eingerückt werden , müssen befolgt werden ;und eine neue Linie ! )

2. Springe mit einem goto über den Code :

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

Live-Beispiel: http://codepad.viper-7.com/UfqrIQ

3. Überspringen Sie den Code mit if(false)oder if(0):

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

Test: http://codepad.viper-7.com/wDg5H5

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.