2010-01-27 4 views
7

Beim Testen einer Antwort für another user's question fand ich etwas, das ich nicht verstehe. Das Problem bestand darin, alle wörtlichen \t\n\r Zeichen aus einer Zeichenfolge mit einem einzelnen Leerzeichen zu ersetzen.Extra Backslash in PHP Regexp Muster benötigt

nun das erste Muster habe ich versucht war:

/(?:\\[trn])+/ 

, die überraschenderweise nicht funktionierte. Ich habe das gleiche Muster in Perl versucht und es hat gut funktioniert. Nach einigem Versuch und Irrtum fand ich, dass PHP will 3 oder 4 Schrägstriche für das Muster zu entsprechen, wie in:

/(?:\\\\[trn])+/ 

oder

/(?:\\\[trn])+/ 

diese Muster - zu meiner Überraschung - beide arbeiten. Warum sind diese zusätzlichen Backslashes notwendig?

+1

Perl reguläre Ausdrücke in die Sprache integriert sind, so dass Sie nur zwei Schrägstriche müssen. –

Antwort

12

Sie benötigen 4 Schrägstriche 1 in regex zu vertreten, weil:

  • 2 Schrägstriche für URL-Kodierung in einem String verwendet werden ("\\\\" -> \\)
  • 1 Backslash für URL-Kodierung in dem Regex-Engine verwendet wird (\\ -> \)

Von der PHP doc, Flucht

jedes andere Zeichen in der umgekehrten Schrägstrich führen wird 1

daher auch gedruckt für \\\[,

  • 1 Backslash wird verwendet, um URL-Kodierung der \, eines bleiben, weil \[ ungültig ("\\\[" -> \\[)
  • 1 Unscharfe wird für Unescaping in der Regex-Engine verwendet (\\[ -> \[)

Ja, es funktioniert, aber keine gute Praxis.

2

Der reguläre Ausdruck ist nur /(?:\\[trn])+/. Aber da Sie müssen auch die Schrägstriche in Zeichenfolge Erklärungen zu entkommen, muss jeder Backslash mit \\ ausgedrückt werden:

"/(?:\\\\[trn])+/" 
'/(?:\\\\[trn])+/' 

Nur drei Rücktasten funktionieren auch, weil PHP kennt nicht die Escape-Sequenz \[ und ignoriert es. So wird \\\ werden aber \[ bleibt \[ bleiben.

+0

Warum funktionieren dann 3 Backslashes? Und warum unterscheiden sich in diesem Fall keine einfachen Anführungszeichen von doppelten Anführungszeichen? –

+0

@kemp: Meine Antwort wurde aktualisiert. – Gumbo

+0

Gumbo :: nur so weiß ich, wenn ich richtig verstanden habe - dieser Fall funktioniert, weil '\ [' ist kein Kontrollzeichen ** und ** es wird keine literale offene eckige Klammer, weil das Muster von links nach rechts geparst wird Also wird der Backslash an den vorhergehenden angehängt und zuvor geflüchtet? –

8

Seine Werke in Perl, weil Sie, dass direkt als RegexMuster passieren /(?:\\[trn])+/

aber in php, müssen Sie als String übergeben, müssen also zusätzlich selbst für Backslash.

"/(?:\\\\[trn])+/" 

Die Regex \ ein einzelner Backslash würde '/ \\\\ /' als PHP preg string

-2

Verwenden str_replace anzupassen!

$code = str_replace(array("\t","\n","\r"),'',$code); 

Sollte der Trick

+1

Das beantwortet meine Frage nicht und ist auch falsch, weil str_replace() nicht erlaubt, alle angeforderten Zeichen (wie viele auch immer) mit einem einzigen Zitat zu ersetzen - Sie können sie alle einfach entfernen. –

+0

@ kemp ja es tut. Wenn es nicht entfernt wird, wie es ist, versuchen Sie Kombinationen von \ r \ n oder \ n \ r – AntonioCS

+1

Nein, Sie können - sagen wir - drei (oder eine beliebige Anzahl) von denen mit einem einzigen Leerzeichen nicht ersetzen, es sei denn, Sie möchten stelle ** jede ** mögliche Kombination zur Verfügung. Was Ihr Code tut, ist nur alle zu entfernen. –