Reguläre Ausdrücke

Artikel, Anleitungen, Minikurse und Leitfaden für alle möglichen PC-Themen und PHP/phpBB.
Antworten
Benutzeravatar
oxpus
Administrator
Beiträge: 28737
Registriert: Mo 27.Jan, 2003 22:13
Wohnort: Bad Wildungen
Kontaktdaten:

Reguläre Ausdrücke

Beitrag von oxpus »

Was soll denn nun dieses bedeuten?
Ein Scherz in der Knowledge Base?
Nein. Ein sehr umfangreiches Kapitel, das selbst den PHP-Interpreter ins Schwitzen bringen kann:

Reguläre Ausdrücke sind Suchmuster, mit denen man Daten innerhalb bestehender Zeichenketten suchen und bearbeiten kann.

Und was soll nun nach dieser doch recht einfachen und verständlichen Kurzbeschreibung die Beschreibung dieses Artikels bedeuten?

Schauen wir dazu doch mal hier hin:

Code: Alles auswählen

	$patterns[] = "#\[url=((www|ftp)\.[^ \"\n\r\t<]*?)\]([^?].*?)\[/url\]#i";
Das ist eine Zeile aus der bbcode.php von OXPUS.de.

Was bewirkt diese Zeile?
Kurz: Diese Zeile beinhaltet das Suchmuster, um Testpassagen wie

Code: Alles auswählen

[url=www.phpbb.com]phpBB[/url]
in echte HTML-Links umzuwandeln.

Ja, wie jetzt? Und was genau bedeuten diese Hieroglyphen denn jetzt :confused:

Genau das ist dann nun Gegenstand dieses Artikels.
Aber keine Angst, es wird kein Artikel mit vielen Beispielen, sondern eher eine Kurzanleitung, was Suchmuster sind und was welche Zeichen bedeuten.
Dann fangen wir doch gleich auch mal an mit der Definition der wichtigsten Begriffe:

Suchmuster werden im POSIX-Format oder in den schnelleren Perl-kompatiblen Schreibweisen (PCRE = Perl Compatible Regular Expressions) geschrieben.
Und genau an die Definitionen des PCRE-Modules in PHP wollen wir uns halten.

Aus was bestehen denn nun Suchmuster?
Neben den diversen Zeichen, wie in der obigen Beispielzeile dargestellt, gibt es zunächst Konstante, die diverse Bedeutungen haben:

PREG_PATTERN_ORDER Sortiert die Ergebnisse so, dass $matches[0] ein Array von Übereinstimmungen mit dem ganzen Suchmuster ist, $matches[1] ein Array von Zeichenketten, die mit dem ersten geklammerten Teil-Suchmuster übereinstimmen und so weiter. Dieses Flag wird nur bei preg_match_all() verwendet.
PREG_SET_ORDER Sortiert die Ergebnisse so, dass $matches[0] ein Array des ersten Satzes von Übereinstimmungen ist, $matches[1] ein Array des zweiten Satzes von Übereinstimmungen und so weiter. Dieses Flag wird nur bei preg_match_all() verwendet.
PREG_OFFSET_CAPTURE Siehe Beschreibung von PREG_SPLIT_OFFSET_CAPTURE. Dieses Flag steht seit PHP 4.3.0 zur Verfügung.
PREG_SPLIT_NO_EMPTY Dieses Flag teilt der Funktion preg_split() mit, dass sie nur nicht-leere Teile zurückgeben soll.
PREG_SPLIT_DELIM_CAPTURE Dieses Flag teilt der Funktion preg_split() mit, dass sie auch die eingeklammerten Ausdrücke des Trennsymbol-Musters zurückgeben soll. Dieses Flag steht seit PHP 4.0.5 zur Verfügung.
PREG_SPLIT_OFFSET_CAPTURE Wenn dieses Flag gesetzt ist, wird für jede gefundene Übereinstimmung auch der dazugehörige Versatz zurückgegeben. Beachten Sie, dass dies die Rückgabewerte in einem Array dahingehend ändert, dass jedes Element ein Array ist, das aus der übereinstimmenden Zeichenkette als erstem und deren Stelle im durchsuchten Text als zweitem Element besteht. Dieses Flag steht seit PHP 4.3.0 zur Verfügung und wird nur bei preg_split() verwendet.

Dazu kommen "Schalter" oder besser Modifikatoren, die das Verhalten des Suchmusters bestimmen:

i (PCRE_CASELESS) Wenn dieser Modifikator gesetzt ist, passen Buchstaben im Suchmuster sowohl auf groß- als auch auf kleingeschriebene Buchstaben.
m (PCRE_MULTILINE) Standardmäßig behandelt PCRE eine zu durchsuchende Zeichenkette wie eine einzige Zeile von Zeichen (auch wenn sie tatsächlich mehrere Zeilenumbrüche enthält). Das Metazeichen für einen Zeilenanfang (^) passt nur auf den Anfang der Zeichenkette, das Metazeichen für ein Zeilenende ($) nur auf das Ende der Zeichenkette (falls der Modifikator D nicht gesetzt ist). Das ist genauso wie bei Perl. Wenn dieser Modifikator gesetzt ist, passen die Zeilenanfang- und Zeilenende-Konstrukte in der Zeichenkette sowohl direkt nach, bzw. vor einem Zeilenumbruch als auch auf deren Anfang und Ende. Das entspricht dem Perl-Modifikator /m. Falls die Zeichenkette keine "\n"-Zeichen enthält, oder im Suchmuster kein ^ oder $ vorkommt, hat dieser Modifikator keine Wirkung.
s (PCRE_DOTALL) Wenn dieser Modifikator gesetzt ist, passt das Metazeichen Punkt im Suchmuster auf alle Zeichen inklusive Zeilenumbrüche. Ohne diesen Modifikator sind Zeilenumbrüche ausgeschlossen. Dieser Modifikator entspricht dem Perl-Modifikator /s. Unabhängig davon, ob dieser Modifikator gesetzt ist, passt eine verneinende Zeichenklasse wie z.B. [ ^ a ] immer auf einen Zeilenumbruch.
x (PCRE_EXTENDED) Wenn dieser Modifikator gesetzt ist, werden Leerräume im Suchmuster ignoriert, sofern sie nicht maskiert sind oder sich innerhalb einer Zeichenklasse befinden. Außerdem werden Zeichen, die außerhalb einer Zeichenklasse zwischen nicht maskierten # stehen, einschließlich dem nächsten Zeilenumbruch ignoriert. Das entspricht dem Perl-Modifikator /x und bietet die Möglichkeit, Kommentare in komplizierte Suchmuster einzufügen. Beachten Sie aber, dass dies nur für Datenzeichen gilt. Leerräume dürfen niemals innerhalb einer Folge spezieller Zeichen auftreten, zum Beispiel in der Folge (?(, die einen bedingten Teilausdruck einleitet.
e Wenn dieser Modifikator gesetzt ist, macht preg_replace() in der Ersetzungszeichenkette eine normale Ersetzung von Rückrefenzen, wertet sie als PHP-Code aus und verwendet das Ergebnis um damit die gesuchte Zeichenkette zu ersetzen. Einfache und doppelte Anführungszeichen werden in den ersetzten Rückreferenzen mit einem Backslash maskiert. Dieser Modifikator wird nur von preg_replace() verwendet; von anderen PCRE-Funktionen wird er ignoriert. Anmerkung: Dieser Modifikator steht in PHP 3 nicht zur Verfügung.
A (PCRE_ANCHORED) Wenn dieser Modifikator gesetzt ist, wird das Suchmuster "verankert", das bedeutet, dass es gezwungen wird, nur auf den Anfang der durchsuchten Zeichenkette zu passen. Diese Wirkung kann auch durch geeignete Konstrukte im Suchmuster selbst erreicht werden, was in Perl die einzige Möglichkeit ist, sie zu realisieren.
D (PCRE_DOLLAR_ENDONLY) Wenn dieser Modifikator gesetzt ist, passt ein Dollar-Metazeichen im Suchmuster nur auf das Ende der durchsuchten Zeichenkette. Ohne diesen Modifikator passt ein Dollarzeichen auch direkt vor dem letzten Zeichen, falls es ein Zeilenumbruch ist (aber nicht vor anderen Zeilenumbrüchen). Wenn der Modifikator m gesetzt ist, wird dieser Modifikator ignoriert. Für diesen Modifikator gibt es in Perl keine Entsprechung.
S Wenn ein Suchmuster mehrmals verwendet werden soll, lohnt es sich, mehr Zeit für dessen Analyse aufzubringen um die Suche zu optimieren. Wenn dieser Modifikator gesetzt ist, wird diese zusätzliche Analyse durchgeführt. Gegenwärtig ist die Untersuchung eines Suchmusters nur für nicht verankerte Suchmuster brauchbar, die am Anfang kein einzelnes fixiertes Zeichen haben.
U (PCRE_UNGREEDY) Dieser Modifikator kehrt die Gier von Quantifikatoren um, sodass sie standardmäßig nicht gierig sind, aber gierig werden, wenn ihnen ein "?" folgt. Das ist nicht mit Perl kompatibel. Es kann auch innerhalb des Suchmusters mit dem Modifikator (?U) oder durch ein Fragezeichen hinter dem Quantifikator (z.B. .*?) gesetzt werden.
X (PCRE_EXTRA) Dieser Modifikator schaltet mit Perl nicht kompatible zusätzliche PCRE-Funktionalität an. Ein Backslash vor einem Buchstaben, der keine spezielle Bedeutung hat, verursacht eine Fehlermeldung und reserviert diese Kombinationen somit für künftige Erweiterungen. Standardmäßig wird ein Backslash vor einem Buchstaben, der keine spezielle Bedeutung hat, wie in Perl als Buchstabensymbol behandelt. Gegenwärtig werden von diesem Modifikator keine weiteren Eigenschaften kontrolliert.
u (PCRE_UTF8) Dieser Modifikator schaltet mit Perl nicht kompatible zusätzliche PCRE-Funktionalität an. Suchmuster werden als UTF-8 behandelt. Dieser Modifikator steht unter Unix seit PHP 4.1.0 und unter Win32 seit PHP 4.2.3 zur Verfügung.

Diese Modifikatoren werden an das Ende eines Suchmusters geschrieben, nach dem Suchmusterbegrenzer (dazu später mehr). Im obigen Beispiel wäre hier das "i" am Ende des Suchmusters der Modifikator. Das Beispiel würde also unabhängig der Groß- und Kleinschreibung suchen.
Soviel auch schon zu den wichtigsten Begriffen in einem Suchmuster, nun zum Eingemachten, den Meta-Zeichen.

Es gibt folgende Meta-Zeichen, die allesamt bestimmte Funktionen innerhalb eines Suchmusters auslösen/darstellen:

\ "Escaped" ein Meta-Zeichen. Es wird dann behandelt, wie ein normales Zeichen.
^ Gibt den Anfang einer Zeichenkette an
$ Gibt das Ende einer Zeichenkette an
. Platzhalter für alle Zeichen, aber nur ein Zeichen lang. Ausgenommen Zeilenumbrüche
[ Beginn einer Zeichenkettendefinition
] Ende einer Zeichenkettendefinition
| Alternative Zeichenketten. In etwa vergleichbar mit "ODER", hat aber nicht immer die gleiche Bedeutung!
( Beginn eines Submusters
) Ende des Submusters
? Erlaubt eine beliebige oder keine Anzahl beliebiger Zeichenketten vor der betreffenden Stelle
* Keine oder mehrere Wiederholungen der Zeichen
+ Eine oder mehrere Wiederholungen der Zeichen
{ Beginn einer Wiederholungsangabe
} Ende einer Wiederholungsangabe

Diese Zeichen sind dann auch schon alle Meta-Zeichen. Nicht viele und dennoch können sie in Kombination die Lesbarkeit eines komplexen Suchmusters schon arg einschränken, bis hin zur völligen Unlesbarkeit.

Innerhalb einer Zeichenkettendefinition, also der Angabe, welche Zeichen gesucht werden sollen, die innerhalb eckicker Klammern [ ] gesetzt werden, stellen folgende Sonderzeichen noch ein paar Funktionen zur Verfügung:

\ Wie oben: Escaped ein Meta-Zeichen, bzw. ein Sonderzeichen als einfachen Text innerhalb des Suchmusters
^ Negativiert die Suche. Es dürfen also die angegebenen Zeichen nicht vorkommen.
- Bezeichnet die Reichweite einer angegebenen Zeichenkette von x -(nach) y.
] Beendet die Zeichenkette

Neben dem einfachen Escapen on Meta- oder Sonderzeichen, hat der Backslash auch noch andere Bedeutungen. Er bezeichnet auch Sonderzeichen, die nicht sichtbar sind, wie z.B. der Zeilenumbruch.
Folgende Bedeutungen sind hier vorgegeben:

\a Alarm. Das BEL-Zeichen
\cx "control-x", wobei X ein beliebiges Zeichen sein kann
\e Excape
\f Zeilenvorschub (Formfeed)
\n Neue Zeile (Newline)
\r Zeilenumbruch (Carriage Return)
\t Tabulator
\xhh Zeichen mit hexadezimalen Wert für hh
\ddd Zeichen mit dem oktalen Wert für dd

Gerade \n ist in Texten immer wieder ein wichtiges Merkmahl, um Zeilenumbrüche in HTML-konforme Breaks < b r > (hier aus Darstellungsgründen nur mit Leerzeichen) umwandeln zu können.

Weitere Definitionen für den Backslash:

\d Dezimale Ziffer
\D Alle Zeichen ausser eine dezimalen Ziffer
\s Alle Leerzeichen
\S Alle Zeichern ausser Leerzeichen
\w Alle "Wort"-Zeichen
\W Alle Zeichen ausser einem "Wort"-Zeichen
\b Wortbegrenzung (vorher und nachher ein Leerzeichen)
\B Keine Wortbegrenzung
\A Beginn eines Ausdrucks
\Z Ende eines Ausdrucks oder eines \n am Ende der Zeile
\z Ende eines Ausdrucks

Und damit haben wir alle wichtigen Zeichen und Funktionen für Suchmuster kennen gelernt.
Der Anwendung wollen wir uns nun widmen, anhand des o.g. Beispiels.

Code: Alles auswählen

#\[url=((www|ftp)\.[^ \"\n\r\t<]*?)\]([^?].*?)\[/url\]#i
Wollen wir dieses mal zerlegen und aufschlüsseln. Aufgeführt werden alle Zeichengruppen, die zusammen eine Bedeutung haben:

#
Begrenzer des Suchmusters. Am Ende folgt ein "i", um die Groß- und Kleinschreibung zu ignorieren.

\[url=
Suchtext, mit dem die Daten beginnen müssen. Da [ mit einem Backslash escaped ist, gilt die Klammer hier als ein einfaches Zeichen!

(www|ftp)
Es folgt ein "www" oder "ftp" dem BBCode-Tag "[url=". Der senkrechte Strich fungiert hier als ein einfaches "oder".

\.
Der escapte Punkt ist auch hier nur ein einfaches Zeichen, kein Platzhalter. Er trennt ja as Protokoll "www" oder "ftp" von der Domäne

[^ \"\n\r\t<]*?
Der zu suchende Text darf kein Leerzeichen, Zeilenumbruch, Zeilenvorschub oder Tabulator sowie kein "Kleiner"-Zeichen enthalten. Ist ja auch nicht typisch und nicht erlaubt in einem Weblink.
Der nachfolgende Stern bedeutet keine bis beliebige Wiederholung der Zeichenmuster innerhalb des zu durchsuchenden Textes. Das Fragezeichen gibt hier an, daß weitere beliebige Zeichen entsprechend (links von der Position) enthalten sein dürfen.
Die schliessende Klammer beendet das Submuster, welches mit dem Web-Protokoll "www" oder "ftp" beginnt.

\]
Das Ende des URL-Einleitungs-Tags. Auch hier wird die escapete Klammer zum normalen Zeichen dekradiert.

([^?].*?)
Dieses Submuster fragt nach allen Zeichen, die vorkommen können mit ".*?", aber keine Zeichen vorausgehen. Dieses ist dann die Hauptdomain des Links!

\[/url\]
Dieses ist dann letzendlich der BBCode-Endtag von URL "[/url]". Da die Klammern [ ] wieder escaped sind, gelten sie auch hier wieder als normale Zeichen.



Damit wären wie dann auch schon am Ende der Kurzeinführung in reguläre Ausdrücke.
Anhand des hier behandelten Beispiel-Suchmusters kann man diese Suchmuster nun besser erklären und verstehen.
Was bleibt, ist aber die Unwissenheit, wie eine Aufgabe mittels regulären Ausdrücken umzusetzen sind, um die gewünschten Ergebnisse zu erhalten.

Nun, an dieser Stelle sei auf das Topic zu diesem Artikel verweisen, in dem wir dann nützliche, unmögliche und noch so komplexe Ausdrücke zerlegen und erstellen werden.
Zuletzt geändert von oxpus am Di 08.Nov, 2005 11:41, insgesamt 1-mal geändert.
Karsten Ude
-={ Das Mädchen für alles }=-
Kein Support per Messenger, Email oder PN! Unaufgeforderte Nachrichten werden ignoriert!
No support per Messenger, Email or PM. Each unasked message will be ignored!
Benutzeravatar
Bootenks
Beiträge: 1836
Registriert: Sa 29.Mai, 2004 23:36
Wohnort: G?rlitz (?stlichste Stadt Deutschlands)

Beitrag von Bootenks »

Ansich sind reguläre Ausdrücke eines der besten Features von php. Es gibt schon einige lustige php Funktionen, aber die wichtigste und beste bleibt preg_match, genau die regulären Ausdrücke in Perl!!! Erste Sahne. ^^

Man muss halt wissen dass z.B. der . für alle Zeichen ausser Zeilenumbruch steht oder dass ^ (muss vor [ stehen) den Anfang der Zeichenkette anzeigt und $ (muss nach ] stehen) das Ende kennzeichnet. Das sieht man dann ganz witzig immer mit "und" und "oder" Verknüpfungen. *genial* Achja wenn das ^ drinnen vor einem Ausdruck steht dann ist damit gemeint das eben dieser Ausdruck nicht enthalten sein soll. Das geht so weiter und so weiter ^^ ...
Zuletzt geändert von Bootenks am Fr 27.Mai, 2005 16:40, insgesamt 1-mal geändert.
Nur ein Informatik Student. ^^
Twins

Beitrag von Twins »

Code: Alles auswählen

Not Found
The requested URL /kb.php was not found on this server.

Apache/1.3.31 Server at www.oxpus.de Port 80
Benutzeravatar
cback
Beiträge: 1391
Registriert: Sa 15.Mai, 2004 15:32
Wohnort: Saarland
Kontaktdaten:

Beitrag von cback »

Kein Kommentar :mad:
Benutzeravatar
oxpus
Administrator
Beiträge: 28737
Registriert: Mo 27.Jan, 2003 22:13
Wohnort: Bad Wildungen
Kontaktdaten:

Beitrag von oxpus »

:motz:
Karsten Ude
-={ Das Mädchen für alles }=-
Kein Support per Messenger, Email oder PN! Unaufgeforderte Nachrichten werden ignoriert!
No support per Messenger, Email or PM. Each unasked message will be ignored!
Benutzeravatar
cback
Beiträge: 1391
Registriert: Sa 15.Mai, 2004 15:32
Wohnort: Saarland
Kontaktdaten:

Beitrag von cback »

*Oxpus Valium geb* ^b
Benutzeravatar
oxpus
Administrator
Beiträge: 28737
Registriert: Mo 27.Jan, 2003 22:13
Wohnort: Bad Wildungen
Kontaktdaten:

Beitrag von oxpus »

Danke, es geht wieder.
Karsten Ude
-={ Das Mädchen für alles }=-
Kein Support per Messenger, Email oder PN! Unaufgeforderte Nachrichten werden ignoriert!
No support per Messenger, Email or PM. Each unasked message will be ignored!
Benutzeravatar
AmigaLink
Beiträge: 5843
Registriert: Mi 03.Mär, 2004 09:05
Wohnort: NRW
Kontaktdaten:

Beitrag von AmigaLink »

:lame: :bofl:
[center].: Web Relax .::. Essen mit Freude .::. AmigaLink.de :.
______________________________________

Kein Support per PM, ICQ oder eMail!!!
[/center]
Antworten