preg_replace, pattern syntax speziell: Zeichenklassen

Fragen zu allen Themen rund ums Programmieren außerhalb von phpBB können hier gestellt werden - auch zu anderen Programmiersprachen oder Software wie Webservern und Editoren.
Antworten
Benutzeravatar
mgutt
Mitglied
Beiträge: 2999
Registriert: 31.08.2004 16:44
Wohnort: Hennef
Kontaktdaten:

preg_replace, pattern syntax speziell: Zeichenklassen

Beitrag von mgutt »

ich versuche mich an eigenen search und replace regeln.

dafür möchte ich erstmal exakt die variante verstehen, die phpbb in der bbcode.php verwendet:

Code: Alles auswählen

$ret = preg_replace("#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $ret);
ich nehme das mal soweit auseinander, wie ich das verstehe:
  • "$ret =" -> der Variable wird ein Inhalt zugewiesen
  • " preg_replace() -> die Funktion "preg_replace(Suchmuster, Ersatz, Zeichenkette)" wird aufgerufen.
  • " -> Suchmuster beginnt
  • # -> Startmarkierung (kann beliebig sein, phpBB verwendet in der Regel das Rautezeichen
  • () -> Klammer stellen hier Teilsuchmuster dar. D.h. die Zeichenkette wird auf bestimmte Teile untersucht. In diesem Fall haben wir zwei Teilsuchmuster: (^|[\n ]) und ([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*). Das Teilsuchmuster wird durchnummeriert und kann dann im Ersatzteil einzeln zugewiesen werden. Das erste Teilsuchmuster wird zu \\1 und das zweite zu \\2 usw.
  • ^ -> Beginn einer Zeile (z.b. ein Link direkt am Anfang eines Beitrages, hat kein Leerzeichen oder Zeilenumbruch davor und würde ohne das ^ nicht umgewandelt)
  • | -> "oder". Innerhalb dieses Teilsuchmusters gib es zwei verschiedene Möglichkeiten. Entweder trifft das ^ oder das [\n ] zu.
  • [\n ] -> Zeichenklasse. Hier werden bestimmte Zeichen erlaubt oder verboten. In unserem Fall bedeutet [\n ], dass \n (also ein Zeilenumbruch und ein Leerzeichen erlaubt sind. Verbote werden innerhalb der Zeichenklasse mit ^ eingeleitet. z.b. [^plus] würde die Zeichenkette "plus" verbieten.
  • ) -> Teilsuchmuster wird beendet \\1
  • ( -> neues Teilsuchmuster beginnt \\2
  • [\w]+? -> Zeichenklasse. Hier stellt \w jeden Buchstaben(a-z, A-Z) oder Zahl (0-9) dar plus den Unterstrich. Man könnte das auch der Zeichenklasse [a-zA-z0-9_] gleichsetzen. Das Pluszeichen nach der Zeichenklasse gibt an, dass mindestens ein Zeichen vorhanden sein muss oder bis zu unendlich viele, aber diesmal folgt ein Fragezeichen. Damit wird erzeugt, dass eine minimale Anzahl an Zeichen gesucht wird. mehr...
  • :// -> Dies ist eine reine Zeichenfolge, die erfüllt werden muss. Man erkennt bereits, dass es dass :// aus http://domain ist.
  • [\w\#$%&~/.\-;:=,?@\[\]+]* -> Die nächste Zeichenklasse. Der Stern am Ende gibt im Gegensatz zum Plus an, dass auch keines der Zeichen in den eckigen Klammern folgen kann. Deswegen wird auch aus http:// in phpBB ein Link. Ob das sinnvoll ist, sei mal dahin gestellt.
  • \w -> jeder Buchstabe (a-z, A-Z) oder Zahl (0-9) plus den Unterstrich
  • \# -> Im Gegensatz zu anderen Stellen, muss man hier aufpassen. Das Backslash stellt hier diesmal nicht wie bei \w einen speziellen Typ dar, sondern das Rautezeichen wird escaped. Das wurde gemacht, weil das Rautzeichen ja als Start- und Endmarkierung genutzt wird und ohne das Rautzeichen zu escapen würde die Zeichenkette an dieser Stelle abbrechen (= Fehler).
  • $%&~/.\-;:=,?@ -> Diverse Zeichen sind erlaubt. Dollarzeichen, Prozent, Ampersand, ~, Slash, Punkt und nun folgt wieder ein \-. Das Minuszeichen ist normalerweise um eine neue character range anzugeben. Das wird z.B. verwendet, wenn man bestimmte Zeichen des Alphabets erlaubt: [a-cA-D] Hier werden die Buchstaben: a, b, c und A, B, C und D erlaubt. Daher müssen wir das Minuszeichen auch escapen, damit es in der Zeichenkette gesucht werden kann. (sonst wieder Fehler). Danach folgen Semikolon, Doppelpunkt, Undzeichen, Komma, Fragezeichen und das At-Zeichen. Dann folgen die eckigen Klammern (diese wurden wieder escaped \[ und \]). Und als letztes das Pluszeichen. Durch den Stern am Ende der Zeichenklasse wird jedes Zeichen erlaubt und es ist egal, wie oft es vorkommt. Soll heißen das wird natürlich auch ein Link: http://$$$&...=++[]]?. Störend empfinde ich die Tatsache, dass der letzte Punkt immer mit in den Link genommen wird. So werden Links am Ende eines Satzes leider zu falschen Links: www.phpbb.de/download.php.
  • ]* -> Das Ende der Zeichenklasse. Der Stern sagt wie gesagt aus, dass keines oder bis zu unendlich viele Zeichen erlaubt sind.
  • ) -> Das zweite Teilsuchmuster wird beendet \\2
  • # -> Das Rautezeichen ist unsere Endmarkierung
  • i -> Buchstaben nach der Endmarkerung sind Modifikatoren. Sie erlauben und verbieten zusätzlich. i erlaubt Groß- und Kleinbuchstaben. Das Verhältnis zwischen \w und i ist mir nicht ganz bekannt.
  • s -> Damit wird der Punkt und Zeilenumbrüche erlaubt. Das Verhältnis zu \n und dem einfachen erlauben des Punktes in einer Zeichenklasse sind mir auch nicht bekannt
  • " -> Suchmuster endet
  • " -> Suchmuster beginnt
  • \\1<a href=\"\\2\" target=\"_blank\">\\2</a> -> Ersatz. Die Teilsuchmuster werden hier nun in einen HTML-Tag eingesetzt. Das erste Teilsuchmuster war übrigens wichtig dafür, dass Links nur dann ersetzt werden, wenn ein Leerzeichen oder ein Zeilenumbruch davor steht. Denn wenn man einen Link in einem Tag einschließt http:// oder direkt davor ein anderes Zeichen steht, dann wird er nicht umgewandelt. Leider auch nicht, wenn er in einer Klammer steht (http://) oder ähnliches.
  • " -> Suchmuster endet
  • $ret -> In dieser Variable wird nach dem "Suchmuster" gesucht und im Fall eines Treffers mit "Ersatz" ersetzt. $ret ist übrigens der Text in einem Beitrag ;)
Wenn ich die Liste vervollständigen könnte, würde das sicher auch anderen helfen.

Dinge, die mir nicht ganz klar sind, habe ich fett geschrieben.

Gruß
meine Foren: http://www.maxrev.de/communities.htm
Ich kaufe Dein Forum! Angebote bitte an marc at gutt punkt it
Dennis63
Ehemaliges Teammitglied
Beiträge: 2597
Registriert: 02.07.2003 18:46

Beitrag von Dennis63 »

http://de2.php.net/manual/de/reference. ... syntax.php

Da steht viel beschrieben.

Es wäre sicherlich auch einfacher, mit kleinen Beispielen zu beginnen.

Grüße
Dennis
Benutzeravatar
mgutt
Mitglied
Beiträge: 2999
Registriert: 31.08.2004 16:44
Wohnort: Hennef
Kontaktdaten:

Beitrag von mgutt »

Mein Hauptproblem ist es zwischen Greedy und Ungreedy zu unterscheiden.

Verwendet man statt dem Originalcode:

Code: Alles auswählen

$ret = preg_replace("#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $ret);
dann nur: (+? wurde gegen + ersetzt)

Code: Alles auswählen

$ret = preg_replace("#(^|[\n ])([\w]+://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $ret);
ändert sich bei mir nichts.

ich dachte in dem moment eigentlich, dass http:// http:// nicht zweimal ersetzt, sondern einmal ersetzt würden und dadurch eines rausfällt. aber anscheinend wirkt sich hier das ungreedy auf eine etwas andere zeichenkette aus, die ich noch nicht heraus habe.
meine Foren: http://www.maxrev.de/communities.htm
Ich kaufe Dein Forum! Angebote bitte an marc at gutt punkt it
Benutzeravatar
S2B
Ehemaliges Teammitglied
Beiträge: 3258
Registriert: 10.08.2004 22:48
Wohnort: Aachen
Kontaktdaten:

Beitrag von S2B »

Soweit ich das sehe, ist das ? im Prinzip an dieser Stelle sinnlos. Das einzige, das ich mir vorstellen könnte, wäre, dass das Fragezeichen aufgrund von der Abwärtskompatibilität des phpBB's zu PHP3 eingefügt wurde. :wink:
http://http:// wird nicht durch ein einfaches http:// ersetzt, da die vordefinierte Zeichenklasse \w nur sog. Wort-Identifier-Zeichen enthält (\w = [0-9A-Za-z_]), deshalb werden sowohl Doppelpunkte als auch Shashs nicht erfasst.
Gruß, S2B
Keinen Support per ICQ/PM!
Hier kann man meine PHP-Skripte und meine MODs für phpBB runterladen.
Benutzeravatar
mgutt
Mitglied
Beiträge: 2999
Registriert: 31.08.2004 16:44
Wohnort: Hennef
Kontaktdaten:

Beitrag von mgutt »

Das denke ich auch.

Und wie ist es bei den Modifikatoren?

\w sagt doch aus, dass buchstaben gemeint sind. warum muss ich dann am ende noch i angeben und das wiederrum erlauben?
meine Foren: http://www.maxrev.de/communities.htm
Ich kaufe Dein Forum! Angebote bitte an marc at gutt punkt it
Benutzeravatar
S2B
Ehemaliges Teammitglied
Beiträge: 3258
Registriert: 10.08.2004 22:48
Wohnort: Aachen
Kontaktdaten:

Beitrag von S2B »

Das kann ich mir auch nur durch Abwärtskompatibilität erklären, imho hat sich seit PHP3 doch einiges an PCRE getan...
Gruß, S2B
Keinen Support per ICQ/PM!
Hier kann man meine PHP-Skripte und meine MODs für phpBB runterladen.
Antworten

Zurück zu „Coding & Technik“