Tutorial Reguläre Ausdrücke

"Reguläre Ausdrücke" sind eine Art Sprache, die beim Programmieren für diverse Problemlösungen verwendet werden kann, insbesondere dann, wenn es darum geht, Zeichenketten (Strings) zu bearbeiten, zu prüfen oder in ihnen etwas zu suchen.

Und weil der Name "Reguläre Ausdrücke" etwas unhandlich ist, heißen die "Regular Expressions" auch oft einfach nur "RegEx(en)".

Du kannst dir dieses Tutorial ausdrucken - es gibt eine Druckversion ohne den schwarzen Hintegrund, wenn du in deinem Browser auf die Drucken-Funktion gehst.

Und für Fehler bitte nicht gleich schlagen, der Text ist zu 100% im Regionalexpress zwischen Dillingen und Trier entstanden :-)

Einführung

Hier gibts ein kleines Tutorial zu diesen esoterisch anmutenden aber unglaublich mächtigen Zeichenketten, die beim unbedarften Betrachter Assoziationen eines kleinen Kindes und dessen ersten Versuchen an der Tastatur auslösen.

Was sind reguläre Ausdrücke? Wie gesagt, können mit regulären Ausdrücken Zeichenketten auf eine bestimmte Zusammensetzung geprüft werden, wie dies z.B. bei Anwendungen wichtig ist, die Eingaben eines Benutzers erwarten.

Beispiele:
  • Schulnote
  • Postleitzahl
  • E-Mail-Adresse
  • Bestellnummern

Konkrete Anwendung

Populäre Stellen, an denen man auf reguläre Ausdrücke stoßen kann und an denen du dieses Wissen anbringen kannst:
  • Web-Anwendungen (z.B. in PHP, Perl)
  • Unix-Skripte
Im Folgenden wird davon ausgegangen, dass du eine entsprechende Stelle vorliegen hast und dich bereits informiert hast, wie reguläre Ausdrücke in der Umgebung deiner Wahl verwendet werden. In PHP geschieht dies z.B. mit den Funktionen preg_match (Prüfen von Strings, finden von Zeichenketten) und preg_replace (Ersetzen von Zeichenketten). Am Besten testest du deinen Ausdruck zuerst "auf dem Trockenen". Dazu kannst du den Regex-Coach benutzen.

Weitere Quellen für Informationen findest du in meinen Links.

Guter Stil

Oft wirst du feststellen, dass es zu einem Problem viele verschiedene Lösungen gibt. Dabei stehen sich dann gegenüber
  • Eine genaue Lösung und eine allgemeinere. Besteht die Gefahr, dass die genaue Lösung zu "restriktiv" ist (und damit vielleicht ein Benutzer frustriert aufgibt, wenn seine richtige Eingabe nicht akzeptiert wird), nimm lieber die allgemeine. Ist das Problem aber sehr "eindeutig", nimm lieber die genaue.
  • Eine genaue Lösung und eine schnelle. Lange reguläre Ausdrücke können viel Zeit für die Verarbeitung in Anspruch nehmen. Auch hier musst du abwägen, was dir wichtiger ist. Es könnte Benutzer ärgern, wenn die Prüfung einer Eingabe sehr lange dauert.
  • Eine einfache Lösung und eine "elegante". Du kannst in 10 Zeichen ausdrücken, was andere nicht in 60 schaffen? Prima, aber denk dran dass du vielleicht später nochmal was ändern willst! Und das kann schwerer werden, als man denkt. Daher nimm lieber die einfachere Variante oder kommentiere komplizierte Ausdrücke.

Probleme

Wenn dein regulärer Ausdruck Probleme macht, du dir aber ziemlich sicher bist dass er richtig ist, schau dir zunächst mal weiter unten die Sonderzeichen an und was man mit ihnen machen muss, um sie zu benutzen. Dabei sind Sonderzeichen schon so "banale" Sachen wie ein Punkt.

Außerdem solltest du ihn dringend im o.g. RegEx-Coach testen! Dieser fördert manchmal geradezu unglaubliche irreguläre Verhaltensweisen zutage ;-)

Dann darfst du als nächstes Google benutzen ;-) Da findet man sehr viele Informationen, viele Vorlagen um diverse Problemstellungen regulär auszudrücken und auch die Google-Groups sind immer hilfreich.

Konventionen

In diesem Tutorial werden folgende Farben für Texte (Strings) verwendet: Regulärer Ausdruck, den du theoretisch so verwenden kannst, mit
markierten neuen Teilen
Absichtlich fehlerhafter Code
Öfters verwende ich mal den Programmierern nicht fremden "String" (und nein, ich spar mir jetzt den Unterwäsche-Witz) für ein Textstück. Außerdem gilt: ein Ausdruck "trifft" = "beschreibt einen Text genau" = "erledigt die gewünschte Funktion" = "matcht" = "frisst (etwas)"

Einfache Ausdrücke

Ein-Elementige reguläre Ausdrücke

Fangen wir mal klein an. Wir wollen prüfen, ob eine Eingabe einer Schulnote von 1-6 entspricht. [123456] erledigt das für uns. Du siehst: in eckigen Klammern folgt eine Auflistung von Zeichen, die erlaubt sind. Insgesamt steht der gesamte geklammerte Ausdruck aber nur für ein Zeichen: 1 oder 2 oder ... oder 6.

Da unsere Zahlen von 1 bis 6 so schön aufeinanderfolgen, können wir auch schreiben [1-6] was die Sache etwas übersichtlicher macht. Genau so könnte man z.b. prüfen, ob eine Eingabe einem Gleis auf einem Bahnhof entspricht: [1-9] für einen Bahnhof mit 9 Gleisen. Auf unserem Bahnhof sei heute Gleis 4 gesperrt, also als Eingabe nicht erlaubt: [1-35-9] Wir haben den Eingabebereich also aufgeteilt in zwei Bereiche 1-3 und 5-9. Du siehst: Die beiden Bereiche werden einfach hintereinander geschrieben. Das ist am Anfang gewöhnungsbedürftig (intuitiv möchte man vielleicht ein Leerzeichen machen), aber das wird uns noch öfter begegnen.

Mehrelementige reguläre Ausdrücke

Was ist, wenn auf unserem Bahnhof jetzt angebaut wird? Sagen wir, er wird auf 12 Gleise erweitert: [1-12] (Gleis 4 sei wieder geöffnet ;-) ). Aber Vorsicht, hier ist ein Fehler drin!

Wie oben erwähnt, steht der gesamte Ausdruck in den eckigen Klammern nur für ein Zeichen. "12" enthält aber zwei Zeichen. Der Code oben wird nicht funktionieren: Er bedeutet "1 bis 1" oder "2". Den Umgang mit Bahnhöfen mit mehr als 9 Gleisen demonstrieren wir später.

Für den Moment wollen wir etwas anderes Prüfen: Bahnsteige 1-9 haben noch jeweils Abschnitt "a" und "b". Wir wollen also auf 1a,1b,2a,...,9a,9b prüfen: [1-9][ab] Will heißen: Eine Zahl 1-9 gefolgt von einem Buchstaben a oder b.

Mehrere rechteckige Klammern entsprechen also mehreren Zeichen. Soll ein Ausdruck mehrere Zeichen beschreiben, werden diese einfach hintereinander gehangen. Dann wird die Eingabe von links nach rechts mit deinem Ausdruck verglichen.

Selbstverständlich müssen auch nicht immer alle Buchstaben aufgeführt werden: [1-9][a-d] trifft jetzt auch z.B. 4d.

Zu beachten ist, dass Groß- und Kleinschreibung getrennt behandelt wird. Eine sinnvolle Erweiterung wäre also z.B. [1-9][a-dA-D]

Optionen

Schauen wir uns die Eingabe einer Hausnummer an. Diese können aus einer oder mehreren (bis zu 3) Ziffern bestehen und ein a-z am Ende haben. Müssen aber nicht. [1-9][0-9]?[0-9]?[a-z]? Das Fragezeichen hinter einem Element (und [1-9] ist ein Element!) besagt: Das vorhergehende Element kann vorkommen, muss aber nicht.

Der letzte Code heißt also: Eine Ziffer (1-9), optional zwei weitere Ziffern (0-9), optional ein Buchstabe.

Stellt man sich solch eine Konstruktion mit z.B. 10 Ziffern vor, kann man sich leicht ausmalen, dass sie schnell sehr lang wird. Daher gibt es eine andere Schreibweise, wenn man ein Element mehr als ein mal erlauben will: a{1,3}h Trifft auf "ah" genau so wie auf "aaah". Die Angabe in Klammern steht also für die {minimale, maximale} Anzahl an Zeichen. Daher können wir unsere Hausnummern auch so formulieren: [1-9][0-9]{0,2}[a-z]? und dann auch ohne Probleme für längere Straßen (USA ;-) ) umschreiben: [1-9][0-9]{1,4}[a-z]? erlaubt jetzt auch Hausnummern im fünfstelligen Bereich, fordert aber mindestens eine zweistellige (beachte die Änderung vor dem Komma).

Eine Konstruktion wie [0-9]{5} (also eine Klammer mit nur einer Angabe) verlangt eine genau x-malige Wiederholung des davorstehenden Ausdrucks. In unserem Fall 5 mal: Dieser reguläre Ausdruck wäre geeignet, um (deutsche) Postleitzahlen zu prüfen.

Wir könne auch ein "mindestens" ausdrücken: [0-9]{3,} fordert eine mindestens 3-malige Wiederholung einer Ziffer.

Beliebige Wiederholungen

Bisher mussten wir immer wissen, wieviele Zeichen gefunden werden sollen. Es gibt aber durchaus Fälle, in denen sich ein Zeichen beliebig oft wiederholen darf.

Schauen wir uns die Prüfung von Telefonnummern an. Wenn man einen regulären Ausdruck schreibt, empfiehlt es sich oft, zunächst einmal zu notieren, auf was dieser alles treffen soll. Unsere Telefonnummern sollen von diesem Format sein dürfen:
  • 0651/55541-36
  • 0049 160 555678
  • 0180.23.555.63
Es können neben Zahlen also auch Bindestriche, Querstriche, Leerzeichen und Punkte vorkommen. Ein gültiges Element wäre also [0-9/. -] (Also: Dieses eine Zeichen besteht aus einer Zahl zwischen 0 und 9 oder einem Slash oder einem Punkt oder einem Leerzeichen oder einem Minus.) Doch Vorsicht! Wie du siehst, kommen in den Klammern zwei Bindestriche vor: ein mal in einer speziellen Funktion, um einen Zahlenbereich anzudeuten und ein mal als "echter" Bindestrich, der so auftauchen darf. Um Verwechslungen auszuschließen müssen wir letzteren maskieren, also zeigen dass er hier keine spezielle Funktion hat. Das geht mit einem vorangestellten Backslash: [0-9/. \-] Und dann wollen wir ja noch mitteilen, dass diese Zeichen beliebig oft vorkommen dürfen: [0-9/. \-]+ Das Plus bedeutet: ein oder mehrmals das davor befindliche Zeichen, also mindestens ein mal. Wollen wir auch eine leere Telefonnummer zulassen (der Mathematiker würde sagen: Die Nullnummer), so gibt es dazu ein anderes Zeichen: [0-9/. \-]* trifft jetzt auch auf "" (leere Zeichenkette) und natürlich unsere Telefonnummern.

Also nochmal zusammengefasst: Das + steht für eine mindestens einmalige Wiederholung. * heißt: keinmal oder beliebig oft.

Platzhalter

Gehen wir zu einem anderen Beispiel über: Wir möchten in einer Bibliothek nach einem Autor suchen, wissen aber nicht, ob er evtl. einen zweiten Vornamen hat. Nach dem Vornamen können also beliebige Zeichen kommen und danach dann erst der Nachname. Eine mögliche Lösung sieht so aus: Marius .*Osterhase Die im Einzelnen bedeutet: "Marius", danach ein Leerzeichen gefolgt von einem beliebigen Zeichen (dafür steht der Punkt!) beliebig oft (also evtl. auch gar keins) und anschließend der Nachname. Das trifft auf "Marius Osterhase" genau so wie auf "Marius Müller Osterhase".

Genau so kann man dem Punkt natürlich auch ein Plus folgen lassen, um mindestens ein beliebiges Zeichen zu fordern.

Der Punkt "frisst" normalerweise zwar fast alles, aber keine Zeilenumbrüche. Wie du ihn dazu bringst, findest du unter Modifikatoren.

Dem "aufmerksamen Leser" wird nicht entgangen sein, dass wir oben auch schon einen Punkt hatten, und zwar innerhalb der eckigen Klammern. Wie bei vielen, aber nicht allen Sonderzeichen müssen diese zwar außerhalb von eckigen Klammern als solche maskiert werden (Backslash davor), aber nicht innerhalb.

Zeichenklassen negieren

Angenommen wir wüssten den zweiten Vornamen des Autors nicht genau, aber können uns daran erinnern, dass er kein q und kein z enthält. Auch kein Problem: Marius [^qz]+ Osterhase verlangt nach einem zweiten Vornamen (deswegen das Plus) und lässt dazu ein beliebiges Zeichen zu, das nicht q oder z ist. Das ^ negiert also eine Zeichenklasse und gilt genau bis zur schließenden Klammer.

Klammern

Klammern können dazu benutzt werden, längere Ausdrücke zu einem Element zusammenzufassen und es damit zu ermöglichen, das oben gelernte auch auf Teilausdrücke anzuwenden: Marius (Müller )?Osterhase trifft genau auf "Marius Müller Osterhase" oder "Marius Osterhase" und auf nichts anderes: Das Fragezeichen bezieht sich - dank der Klammern - auf den kompletten zweiten Vornamen und das folgende Leerzeichen.

Ebenso lässt sich schreiben: Ba(na)*ne Was jetzt sowohl für dieses gelbe Ding als auch z.B. für "Banananane" steht. Auch hier lässt sich die Notation mit den geschweiften Klammern anwenden: Ba(na){2,5}ne was jetzt natürlich eine entsprechend andere Bedeutung hat.

Alternativen

Mit Klammern kann man aber auch noch andere Sachen machen, z.B. Alternativen zu einem Teilausdruck angeben: Das Wetter ist (toll|richtig schlecht) In diesem Beispiel dürfen als letzte Worte "toll" oder "richtig schlecht" vorkommen, aber nicht beide.

Modifikatoren

In allen RegEx-Varianten kannst du sogenannte Modifikatoren setzen und damit das genaue Verhalten des Ausdrucks kontrollieren. In Java kannst du dies z.B. bei der Konstruktion eines matcher-Objektes erledigen, bei PHP hat ein regulärer Ausdruck immer die Syntax [Begrenzungszeichen][RegEx][Begrenzungszeichen][Modifikator(en)] also z.B. /(Mein|Ausdruck)/im Dabei sind "i" und "m" in diesem Fall Modifikatoren. Gängige Modifikatoren sind unter anderem:
  • i Case-Insensitivity (die Nichtbeachtung von Groß- und Kleinschreibung)einschalten
  • s Punkt wird multilinefähig: Der Punkt frisst auch Zeilenumbrüche, dies ist standardmäßig nicht so.
  • m Zeilenmodus: Die Zeichen ^ und $ passen mit auch auf Zeilenanfänge bzw. -enden. Ohne den Modifikator passen sie nur auf Anfang und Ende der gesamten Zeichenkette.
Modifikatoren beziehen sich immer auf den ganzen Ausdruck und sind daher eine leicht übersehene Fehlerquelle.

Kompliziertere Ausdrücke

Verschachtelungen

Selbstverständlich dürfen auch diverse Klammern ineinander geschachtelt werden, wie z.B. in folgendem Ausdruck: (VW (Golf|Polo)|Fiat (Punto|Panda)) welcher auf "VW Golf", "VW Polo", "Fiat Punto" und "Fiat Panda" trifft. Dies ermöglich zwar recht kurze Ausdrücke für lange Zeichenketten, kann aber auch viel Zeit zur Verarbeitung in Anspruch nehmen.

Genau so lassen sich auch diese Alternativen wiederholen: (10|01)+ Beschreibt eine Folge aus Nullen und Einsen, in der maximal 2 Nullen oder Einsen aufeinander folgen. (Falls das jetzt nicht direkt klar wird: einfach mal überlegen, was man aus "10" und "01" zusammensetzen kann.)

Gierige Ausdrücke

Ein Beispiel aus der Praxis: Der folgende, etwas längerer Code soll uns aus einer HTML-Datei die Links bzw. deren Zieladressen heraussuchen. Ein Link in einem HTML-Quellcode hat i.d.R. ein Format wie dieses: <a href="[...Zieladresse...]" [...weitere Angaben...]> z.B. <a href="http://www.example.org/" target="_blank"> Ein möglicher Ausdruck dafür ist recht schnell gefunden: <a href=".*".*> Sieht gut aus, klappt aber nicht. Warum?

Der Autor hat sich zwar gedacht der Ausdruck würde an der zu dem Link gehörenden schließenden Klammer aufhören, er tut es aber nicht. Im folgenden ein Ausschnitt aus einer HTML-Datei mit markiertem Treffer: <BODY> Bla Blubb 1 2 3 <a href="http://www.example.org/" target="_blank"> Linktext </a> Viel, viel weiterer <i>Text</i> Blubb 42 Das geht eindeutig zu weit! Der zweite Punkt ist zu "gierig" und frisst alle Zeichen sogar über mehrere schließende spitze Klammern hinweg. In anderen Situationen wäre es denkbar, dass der erste Punkt ähnlich amokläuft.

Für unseren Fall gibt es zwei Lösungsmöglichkeiten. Oft bleibt jedoch nur eine davon, daher stelle ich beide vor:
  • Den Punkt ersetzen durch etwas was keine spitzen Klammern mehr frisst: <a href=".*"[^>]*> Das ist eine oft anzuwendende Methode (überlege dir, welche Zeichen das Ende markieren und schließe diese von dem zu treffenden aus). Das ganze muss jetzt natürlich noch analog für den ersten Punkt gemacht werden: <a href="[^"]*"[^>]*>

  • Den Punkt "umerziehen" (bzw. * genügsam machen) so dass beide zusammen nur noch so viel fressen, wie unbedingt nötig ist. Dies tut ein angehängtes Fragezeichen, was dann natürlich nicht mehr die bisher bekannte Funktion hat: <a href=".*?".*?> Natürlich funktioniert diese Sonderbenutzung des Fragezeichens auch hinter einem Pluszeichen.

Gruppen

So gut wie alle RegEx-Dialekte erlauben das Bilden von Gruppen und deren Speicherung für spätere Verwendung. Auch dazu können Klammern dienen.

Spätere Verwendung kann z.B. heißen, dass ein Ausdruck zwar auf eine längere Zeichenkette treffen soll, aber nur ein Teil davon wirklich verwendet werden soll.

Soetwas wäre in Verbindung mit dem obigen Ausdruck sehr nützlich, um alle Zieladressen aus einer HTML-Seite zu filtern.

Wie genau du an die Inhalte der Gruppen kommst, steht in der Anleitung der von dir verwendeten Sprache. Bei PHP findest du es z.B. bei preg_match und Java soweit ich mich erinnern kann irgendwo in der Nähe von regex.matcher. Google sollte da mehr zu wissen. <a href="(.*?)".*?> Der erste Punkt und seine "Vervielfacher" sind eingeklammert. In der ersten Gruppe befindet sich jetzt also die URL.

Beachte, dass bei der Nummerierung der Gruppen die Reihenfolge der öffnenden Klammer zählt. Das ist wichtig zu beachten bei verschachtelten Klammern. Außerdem zählen normalerweise alle Klammern, auch wenn sie nur zur Ausweisung von Alternativen (s.o.) verwendet werden.

Referenzen

Es gibt noch einen anderen, sehr nützlichen Verwendungszweck für Gruppen. Stell dir vor, du willst in einer Folge von Zahlen (sagen wir sie seien mit einem Leerzeichen voneinander getrennt) all die Zahlen finden, die mit der selben Ziffer beginnen und enden.

Wir haben also 129 337873 78324 43938 9388 824998 349734 Dazu können wir solch einen Ausdruck verwenden:  ([0-9])[0-9]*\1 wobei das \1 auf den Inhalt der ersten Klammer verweist (referenziert) und daher an der Stelle von \1 das selbe stehen muss wie in dieser Klammer. Das erste und letzte Zeichen unseres Ausdrucks ist jeweils ein Leerzeichen, um damit das Ende und den Anfang einer Zahl zu kennzeichnen.

Schauen wir uns an, auf was er trifft: 129 337873 78324 43938 9388 824998 349734 Wie du siehst, zählt das erste und letzte Leerzeichen auch immer noch zu dem jeweiligen Treffer dazu. Das ist auch kein Wunder, schließlich steht vor und hinter unserem Ausdruck auch jeweils ein Leerzeichen. Das ist nicht wirklich gut, wenn uns dieses Leerzeichen eigentlich gar nicht interessiert. Daher stellt die RegEx-Sprache auch hier ein Mittel zur Verfügung, welches auch funktioniert, wenn wir keine Gruppen benutzen möchten oder können:

Spezielle Zeichen: Wortgrenzen

Es gibt Zeichen, die stehen zwar im regulären Ausdruck, aber nicht in dem Text, der nachher gematcht wird. Das sagt dir jetzt nichts? Naja, schauen wir uns als ein Beispiel an, wie man obigen Ausdruck ohne die Leerzeichen schreibt: \b([0-9])[0-9]*\1\b Dieses "\b" ist ein zusammengehöriges Element und kennzeichnet ein Wortanfang oder ein Wortende (also eine Wortgrenze). Kennst du die in Textverarbeitungsprogrammen und Editoren oft verwendete Möglichkeit "Nur ganzes Wort suchen" in der Suchfunktion? Wählst du diese aus, werden z.B. bei einer Suche nach "Kai" statt diesen Treffern Kai fährt nach
Kaiserslautern
nur noch dieser Treffer gefunden: Kai fährt nach
Kaiserslautern
Letzteres ließe sich in regulären Ausdrücken so umsetzen bzw. ausdrücken: \bKai\b Also "Kai" nur, wenn es von Wortgrenzen umgeben ist. Was genau ist überhaupt eine Wortgrenze? Eine Wortgrenze tritt zwischen einem Wort-Zeichen und einem Nichtwortzeichen auf. Hä? (Erklärung folgt!)

Spezielle Zeichen: Weitere Zeichen

Es gibt - Überraschung! - noch mehr Sonderzeichen, die du verwenden kannst und die eine RegEx schön abkürzen können. Diese bestehen immer aus einem Backslash gefolgt von einem weiteren Zeichen (Buchstaben). Übrigens steht ein großer Buchstabe dabei immer für das Gegenteil eines kleinen. \w  \W Ein Wort-Zeichen (kleines w) steht genau für [a-zA-Z0-9] und ein Nichtwortzeichen (großes W) steht genau für alles andere, also [^a-zA-Z0-9]. \d  \D Ein Digit, also eine Ziffer von 0-9. Entspricht damit [0-9] und in der Großschreibung [^0-9]. \b  \B Die "kleine" Variante hast du ja oben schon kennengelernt. Ein großes B steht dementsprechend für alle Stellen, an denen keine Wortgrenze auftritt. \s  \S Die Kleine Variante steht für alle Whitespaces: Das sind so gut wie alle Zeichen, die man nicht sieht. Also Return (bzw. Enter), Leertaste (Space), Tab(ulator). \\ Wenn man mit Backslash, wie du gesehen hast, Sonderzeichen anfängt, muss man ja auch den Backslash selbst irgendwie fabrizieren können, wenn man genau diesen meint. Dies macht man einfach durch einen doppelten solchen. Man sagt: der erste "maskiert" den zweiten. \.  \+  \*  \(  \)  \[  \]  \-  \$  \| Der Punkt und viele andere Zeichen haben, wie du oben gesehen hast, eine Sonderfunktion. Daher werden sie mittels eines Backslashs von dieser Sonderfunktion abgehalten ("maskiert"). Dies gilt für das Minuszeichen nur innerhalb von Zeichenklassen, dafür darfst du in selbigen bei vielen anderen Zeichen die Backslashs weglassen.

Anfangs- und Endezeichen

Stell dir vor, du willst ein Datum prüfen, sagen wir mit 1\.3\.2004 Und diesen Ausdruck lässt du auf 11.3.2004 los. Was kommt raus? Dein Ausdruck wird dir melden, dass er trifft. Ist ja auch irgendwo klar, schließlich steht, wenn man eine Eins weglässt, dein Datum da. Du willst aber, dass das gesamte Datum wie deins aussieht? Gibt\'s da nicht was von Ratiodingsbums? Doch gibts: ^1\.3\.2004$ Dieses Dach am Anfang sagt: Treffe nur, wenn hier der zu durchsuchende String anfängt. Und das Dollarzeichen steht für: Treffe nur, wenn genau hier der zu durchsuchende String endet.

Selbstverständlich kann man beide auch einzeln einsetzen; Als Beispiel schauen wir uns zwei reguläre Ausdrücke an: Der erste trifft auf einen String, der mit einer Zahl endet. Der zweite trifft auf einen String, der mit einer öffnenden Klammer beginnt. Dabei benutzen wir die oben angegebene Maskierung für die Klammer. \d$
^\(

Positive Lookaheads und Lookbehinds

Du hast jetzt Möglichkeiten kennengelernt, wie du Wortgrenzen feststellen kannst, ohne sie selbst wirklich mitzufressen. Es gibt auch eine universelle Möglichkeit.

Als Beispiel soll folgende Zahlenfolge dienen: 000566403580000345050052301078906040092800100001007680 Aus dieser Zahlenfolge sollen alle jene Folgen heraufgefischt werden, die drei Ziffern ungleich Null enthalten und von einer Null an jeder Seite begrenzt werden. In unserem Fall also "358", "345", "523", "789", "928" und "768". Dazu kannst du folgenden Code benutzen: (?<=0)\d{3}(?=0) Keine Panik! Zur Erklärung, und wir fangen in der Mitte an: das \d{3} sollte klar sein (3 Ziffern). Davor findest du die Klammer (?<=0). Die Zeichen ?<= musst du "en bloc" betrachten und sie kennzeichnen eine Sonderfunktion für die Klammer. Diese steht damit für "vornedran eine Null". Und weil "vornedran" in der normalen Leserichtung der westlichen Welt bedeutet, dass die Klammer "rückwärts" schaut, heißt diese Funktion "positive lookbehind".

Genauso mit den Zeichen "?=", diese weisen der Klammer die Sonderfunktion "hintendran muss ... kommen" zu, in unserem Fall also "hintendran eine Null". Das ganze nennt sich "positive lookahead", weil die Klammer "nach vorne" schaut.

Unser "\b"-Beispiel von oben könnten wir also auch folgendermaßen ausdrücken, wenn wir unser Wissen über "\W" benutzen: (?<=\W)(\d)\d*\1(?=\W) Zur Erklärung fangen wir wieder in der Mitte an: Da steht der von oben bekannte Code (Eine Ziffer, beliebig viele weitere Ziffern und eine weitere Ziffer, die die gleiche wie die erste ist). Die allererste Klammer fordert vor der ersten Ziffer ein Nichtwortzeichen und die allerletzte Klammer ein Nichtwortzeichen hinter der letzten Ziffer.

Selbstverständlich können lookaheads und lookbehinds auch einzeln in einem regulären Ausdruck vorkommen und sogar mehrfach. Das einzige, was nicht geht, ist ein lookbehind mit einer unbekannten Anzahl von Zeichen. (also so Dingern wie *, + und {0,4})

Alles klar? Wenn nicht, dann zurück zum Anfang dieses Abschnitts, gehe nicht über "Los" und ziehe keine 200 RegExen ein.

Negative Lookaheads und Lookbehinds

Du hast das kompliziert gefunden und siehst so langsam ein, wie voodoo reguläre Ausdrücke sind? Es kommt noch besser.

Dazu noch ein Beispiel: Du willst eine E-Mail-Adresse prüfen, die aber nicht aus Frankreich stammen soll. Zunächst schauen wir uns eine einfache E-Mail-Adressen-Prüfung ohne die Einschränkung an: [^@]+@.+\.[^.]+ (Ein Zeichen ungleich dem @-Zeichen, gefolgt von einem @-Zeichen, beliebigen Zeichen (aber mindestens eins), einem Punkt und dahinter beliebige Zeichen, aber kein Punkt mehr. Trifft auf toll@example.com genau so wie auf viele_.Zeichen@noch.mehr.Punkte.example.com.) Wichtig: das letzte Paar von eckigen Klammern frisst immer den letzten Teil (die Top-Level-Domain, im Beispiel "com") der E-Mail-Adresse.

Jetzt fügen wir eine Beschränkung ein und wollen "fr" an dieser Stelle ausschließen. Auf den Punkt darf also nicht "fr" folgen. [^@]+@.+\.(?!fr)[^.]+ erledigt das für uns. ?! kennzeichnet eine Klammer also als "hier darf nicht folgen".

Damit könnte man auch eine besondere Suche nach einem Wort gestalten. \bF(?!eta\b).*\b trifft auf alle Wörter, die mit "F" anfangen, aber ungleich "Feta" sind. Im folgenden Text sind alle Strings markiert, die getroffen werden: Fett Feta Falsch Feucht Fuffziger Das war der "negative lookahead".

Und weils so schön war, leg ich noch einen drauf, den "negative lookbehind": .*(?<!Müll)eimer trifft auf alle Eimer, in die kein Müll gehört, meint also: "treffe an dieser Stelle, wenn davor kein "Müll" steht".

Ich hoffe, dieses kleine Tutorial hat dir etwas durch den Zeichendschnungel der Regulären Ausdrücke geholfen. Falls jetzt noch Fragen offen sind, empfehle ich die oben genannten Websites als Nachschlagewerke. Wenn du das Tutorial hilfreich fandest, würde ich mich auch über eine Spende freuen:
Kommentare (neuste zuerst)
  • Nico Giermann schreibt am 15.10.12 um 11:46 Uhr: Lieber Daniel Fett, das ist mal wirklich ein Klasse Tutorial, gerade als TZelefonanlagen Experte weiß ich, dass einige Hersteller von Software und Programmierschnittstellen von Telefonanlagen wirklich extrem komplizierte Bedienungsanlagen für Ihre Telefonanlagen herstellen. Also meinen herzlichen Dank aus Flensburg an Dich, das ist wirklich ein Meisterwerk und wird mir im täglichen Alltag helfen Aufgaben wie Suchen und Sortieren etc. leichter zu managen. Herzlichst Nico
  • Josh schreibt am 10.09.12 um 10:10 Uhr: Super Tutorial, endlich mal eine Erklärung bei der man das ganze Verstehen kann und nicht gleich mit sowas wie: "Reguläre Ausdrücke sind eigentlich ganz einfach man muss nur $string = preg_replace('/\[\[image:(.+)\|(.+)\]\]/i', "<img src='$1' alt='$2'/>", $string);" ( . . . Hää ?!) bombardiert wird. Danke !
  • replica michael kors handbags schreibt am 13.08.12 um 08:51 Uhr: <a href="http://cheapmikorshandbagsoldes.info/">michael kors outlet online</a> <a href="http://mkorshandbagsoldes.com/">michael kors handbags outlet</a> http://mkorshandbagsoldes.com/
  • Pit schreibt am 03.08.12 um 21:34 Uhr: Danke für das gute Tutorial!
  • Mörtel schreibt am 05.07.12 um 18:36 Uhr: ?<=0)\d{3}(?=0) der Ausdruck ist für das geforderte Ergebnis nicht zulässig, da auch z.b 010 gematcht wird, richtig wäre z.b (?<=0)[1-9]{3}(?=0)
  • Michael schreibt am 19.06.12 um 14:06 Uhr: Spitzen Tutorial! Vielen Dank dafür!
  • Gunter schreibt am 08.06.12 um 16:12 Uhr: Eins der eingängigsten Tutorials, die ich zum Thema gefunden habe. Für mich war vor allem die Lösung gegen den Allesfresser (.*) sehr hilfreich. Danke!
  • share tips schreibt am 27.05.12 um 14:05 Uhr: dieses kleine Tutorial hat dir etwas durch den Zeichendschnungel der Regulären Ausdrücke geholfen.
  • share tips schreibt am 27.05.12 um 14:04 Uhr: mit beispielen.. das vermisse ich auf anderen Seite, ich persönlich lerne nur durch sehende Logik..
  • Excel Training schreibt am 24.05.12 um 05:04 Uhr: Love your blog..keep it running..
  • Diagram schreibt am 20.05.12 um 11:39 Uhr: Super! ich war seit Tagen auf der Suche nach einer verständlichen Tutorial. Eine sehr einfache Einstieg bis es dann richtig sitzt. Toll!!
  • Florian Niefünd schreibt am 11.05.12 um 15:15 Uhr: Super! vielen dank das hat mir auf der Arbeit echt geholfen!
  • Reginald Expo schreibt am 03.05.12 um 09:12 Uhr: Klasse gemacht. Das war das erste Tutorial das ich zu dem Thema wirklich verstanden habe und ich hab schon mehrere Anläufe hinter mir. Das zeigt mal wieder, dass Texte von Entwicklern die ihr Handwerk wirklich verstehen deutlich besser sind als 100-seitige professorale Definitionen und Theorien. Danke für alles.
  • Thomas schreibt am 28.04.12 um 15:14 Uhr: m Zeichenketten können aus mehreren Zeilen bestehen Um ein HTML-File zu durchackern, eignet sich besser als /m der Parameter /s: s Zeichenketten als eine einzige Zeile betrachten
  • schnippselcode schreibt am 25.04.12 um 13:09 Uhr: Nach einigen Anläufen, die erste Regex-Erklärung, die bei mir hängen geblieben ist! Vielen, vielen Dank :-)
  • Abnehmen mit Diät schreibt am 07.04.12 um 11:20 Uhr: Danke für das Tutorial! Bin leider immer noch nicht ganz schlüssig geworden. Kann ich die falsche Version haben?
  • dominik schreibt am 29.03.12 um 15:04 Uhr: Sehr verständlicher und guter Beitrag zu Regex. Danke!
  • Tommy schreibt am 09.02.12 um 23:17 Uhr: ^Vielen Dank! Super Einstieg in das Thema(:-\))*$
  • Noah Kelly schreibt am 07.02.12 um 14:39 Uhr: Vielen Dank für die echt super Erläuterungen. *thumbsup*
  • Uli schreibt am 27.01.12 um 17:10 Uhr: So schreibt man ein Tutorial ...
  • Vitali schreibt am 22.01.12 um 03:40 Uhr: Danke für den sehr Ausführlichen Beitrag zu Regulären Ausdrücken. Habe mich beim Coden immer davor gedrückt und umfangreiche Umwege in Kauf nehmen müssen, werde mich aber jetzt mit Ihrem Tutorial in das Thema einarbeiten.
  • Christian schreibt am 10.01.12 um 14:59 Uhr: Vielen Dank, hat mir echt weitergeholfen.
  • Druckerpatronen schreibt am 19.12.11 um 10:13 Uhr: Danke für das Tutorial. Ich muss zwar schon seit längerem mit Regexen hantieren, aber einige Sachen waren mir bis jetzt nicht wirklich klar. Ein Tutorial in Muttersprache ist da schon ne gute Sache :D
  • Sebastian schreibt am 14.12.11 um 10:56 Uhr: Hey, vielen Dank für das tolle Tutorial.
  • Hochzeitsfotograf schreibt am 09.12.11 um 12:07 Uhr: Für einen regulären Ausdruck brauche ich meist sehr viel Zeit, bis er funktioniert. Danke für die Übersicht!
  • Cherl schreibt am 08.12.11 um 15:10 Uhr: waow...das ist eine super Erklärung vieles, das man wissen wollte zum Thema...Herzlichen Dank!
  • Florian schreibt am 24.11.11 um 10:46 Uhr: Endlich mal ein Tutorial das man auch versteht ;) Hat mir sehr geholfen! Vielen Dank.
  • Stephan schreibt am 23.11.11 um 09:25 Uhr: echt super um mal schnell was nachzulesen. Echt super Informaten... Danke
  • incantare schreibt am 13.11.11 um 00:00 Uhr: danke für das tutorial, hat mir echt geholfen! nach einigem rumprobieren hab ich aber einen fehler gefunden: du schreibst für den ausdruck einer telefonnummer [0-9/. \-]+ der slash / muss hier aber auch maskiert werden, sonst spuckt php einen fehler aus. richtig heißt es so: [0-9\/. \-]+
  • Hannes schreibt am 08.11.11 um 08:40 Uhr: WTF! Genial!
  • David schreibt am 02.11.11 um 09:49 Uhr: @Hussi: ist es nicht vernünftig, das über den XML-Namensraum anzugehen? Bei Einbindung entsprechender Bibliotheken kannst Du mit den Knoten auf anderer Ebene als mit regulären Ausdrücken arbeiten. Evtl. brauchst Du regex dann zusätzlich noch aber diesbezügliche Aufgaben sind dann deutlich reduziert und auf einzelne Werte oder Knoten-Namen reduziert.
  • Hans schreibt am 18.10.11 um 20:35 Uhr: Vielen Dank für dieses nette kleine Tutorial, hilft mir immer wieder!
  • Hussi schreibt am 06.10.11 um 16:13 Uhr: Hi Jungs, ich schreibe ein Programm in C# und möchte per RegEx xml-datei rufen und ein wort(z.B. (*$EINS[DEL]*) ) in dieser Datei suchen danach die ganze Zeile (Node) wo diese Wort ist löschen und danach die xml-datei ohne diese Node (Zeile) in anderen Name speichern Das ist ein Teil von der XML-Datei und Sie sehen das wort (*$EINS[DEL]*) zwischen den Zeilen: <Single Name="Interface" Type="{a9ed5b7e-75c5-4651-af16-d2c27e98cb94}" Method="IArchivable"> <Single Name="TextDocument" Type="{f3878285-8e4f-490b-bb1b-9acbb7eb04db}" Method="IArchivable"> <Array Name="TextLines" Type="{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}"> <Single Type="{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}" Method="IArchivable"> <Single Name="Id" Type="long">2</Single> <Null Name="Tag" /> <Single Name="Text" Type="string">PROGRAM PLC_PRG</Single> </Single> <Single Type="{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}" Method="IArchivable"> <Single Name="Id" Type="long">8</Single> <Null Name="Tag" /> <Single Name="Text" Type="string">VAR</Single> </Single> <Single Type="{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}" Method="IArchivable"> <Single Name="Id" Type="long">18</Single> <Null Name="Tag" /> <Single Name="Text" Type="string">start: BOOL;(*$EINS[DEL]*)</Single> </Single> <Single Type="{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}" Method="IArchivable"> <Single Name="Id" Type="long">10</Single> <Null Name="Tag" /> <Single Name="Text" Type="string">output: BOOL;(*$EINS[DEL]*)</Single> </Single> <Single Type="{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}" Method="IArchivable"> <Single Name="Id" Type="long">3</Single> <Null Name="Tag" /> <Single Name="Text" Type="string">stop : Bool;</Single> </Single> <Single Type="{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}" Method="IArchivable"> <Single Name="Id" Type="long">1</Single> <Null Name="Tag" /> <Single Name="Text" Type="string">END_VAR</Single> </Single> </Array> </Single> </Single>
  • RegEx schreibt am 23.08.11 um 00:41 Uhr: @Marc: Vielleicht hilft dir das hier weiter: http://de.globalsoftwareindex.com/tutorials/45/regulaere-ausdruecke-tutorial-teil-5-zeichengruppen-und-zeichenklassen Stichwort Negation von Zeichen und Zeichenklassen.
  • Jan schreibt am 19.08.11 um 12:52 Uhr: Danke dir. Beste Anleitung zum Thema. Endlich mal ein wenig Durchblick bei diesem Thema.
  • Marc schreibt am 09.08.11 um 16:22 Uhr: Hey, super Seite aber leider finde ich nicht ganz was ich brauche... Ich kriege einfach nicht raus wie ich einen String darauf teste, ob er KEIN Sonderzeichen bis auf "*" und "@" enthält aber das ALLE Buchstaben, also auch ä, ö, ü erlaubt sind ohne dabei alles einzeln aufzuzählen. Könnte ich dazu vielleicht etwas Hilfe bekommen? Bitte Danke
  • Someonelse schreibt am 25.07.11 um 17:54 Uhr: @Trigo Slash muss nicht escapet werden, wenn du das beachtest sollte das was du hattest funktionieren [^(</li>)]* Wenn zwischen den Listelementen Zeilenumbrüche hast, frisst der Punkt sie eh nicht und wird damit nicht zu "gierig". Wenn allerdings innerhalb innerhalb der li-Tags Zeilenumbrüche sind, dann werden die Tags gar nicht erkannt! Dagegen hilft der Modifikator /s. Wenn dich nur der Inhalt der li-tags interessiert, kannst du (?<=<li>)[^(</li>)]*(?=</li>) ausprobieren. Zum Testen und Routine erlangen hilft der o.g. Regex Coach. Ich hoffe das hilft, Someonelse
  • Trigo schreibt am 12.07.11 um 23:41 Uhr: Erst mal vielen Dank für dieses klasse Tutorial! Aber irgendwie komme ich gerade nicht weiter. Ich möchte einzelne Elemente einer HTML Liste auslesen. Mit /<li>(.*)</li>/gi scheint der Punkt zu gierig. Da diese Elemente weitere HTML Elemente beinhalten (können) funktioniert eine Ersetzung des Punktes durch [^<]* nicht, weil es dann zu früh stoppt. Jetzt habe ich einfach versucht, das auszuschließende Zeichen durch eine Zeichenkette ersetze [^(<\/li>)]* aber auch das funktioniert nicht. Irgendeinen Tipp?
  • Gerhard schreibt am 05.07.11 um 14:51 Uhr: Hallo, bin vollkommen neu hier. Welches Zeichen im folgenden Ausdruck lässt die Umlaute und das ß unangetastet? preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9äöüßÄÖÜ()]/", "", $myvar );
  • C. Info schreibt am 01.07.11 um 15:24 Uhr: Super tolles Tutorial zum diesem Thema. Es hat mir gut geholfen mich wieder in die problematik einzuleben.
  • Jens Schmidt schreibt am 06.06.11 um 14:10 Uhr: Und wieder einmal habe ich hier binnen einer Minute die Lösung zu meiner Problemstellung gefunden. Vielen Dank für dieses Tutorial! Grüße aus Freiburg
  • Neodesway schreibt am 03.05.11 um 10:01 Uhr: Danke für das Tutorial!!! Super Erklärt. Ich programmiere im Moment der Balken der Abkürzung STRG-G. Der Benutzer sollte ausstatten, den Anfang aller Ausdrücke wiederzufinden, die er wünscht (zb bei einer nach "Kai": Kai fährt nach Kaiserslautern )Welcher Ausdruck mir erlauben könnte, alle möglichen Symbole wiederzufinden??? Danke.
  • Hasso schreibt am 21.04.11 um 10:01 Uhr: Hallo Daniel, dein Tutorial hat mir sehr weitergeholfen, besonders der Abaschnitt über negativen lookahead. Spende folgt.
  • replaceAll schreibt am 19.04.11 um 13:21 Uhr: Ich habe das hingekommen , ich danke auch für dieses schöne Tutorial.
  • replaceAll schreibt am 18.04.11 um 01:37 Uhr: Hallo Daniel, ich möchte von einem Wort aus einer Vorkabelliste "Umfassung {f}" das " {f}" weg bekommen mit replaceAll("[.]*{f}", ""). Dann bekomme ich diesen Fehler: "Exception in thread "AWT-EventQueue-0" java.util.regex.PatternSyntaxException: Illegal repetition near index 3 [.]*{f}". Ich habe auch schon viele andere Sachen probiert, wie "\\s".
  • Michael S schreibt am 27.03.11 um 21:49 Uhr: Das !Müll)eimer Beispiel ist super!!!
  • Pollewetzer schreibt am 18.03.11 um 15:34 Uhr: Chapeau! - Endlich eine Seite im Web, die mir weiterhilft und dazu noch auf so übersichtliche und einfache weise! - Schließlich will ja nicht jeder erst 500 Seiten lesen (siehe O.Reilly Reguläre Ausdrücke) um weiter zu kommen. Schön wäre es allerdings, wenn gelegentlich die vielen Fragen mal als "extended-Version" aufgearbeitet werden könnten...;-)
  • Flachzange schreibt am 18.03.11 um 10:03 Uhr: Yo, krazz konkret! Respect dude!!
  • ilTino schreibt am 13.03.11 um 12:45 Uhr: Tolles Tutorial! Ich konnte damit fast meine gesamte Logikprüfung machen. Nur ein Problem habe ich. Bei der Mail-Adresse sagt mir eclipse "invalid escape sequence". Meine RegEx ist: [\w_\-\.]+@[\w\-]+.[\w]{2,3}$ Was mache ich falsch?
  • Brautseiten schreibt am 08.03.11 um 15:34 Uhr: Danke für das tolle Tutorial, hat mir sehr weitergeholfen und einen guten Einblick in die RegExen gebracht.
  • anon schreibt am 01.03.11 um 18:35 Uhr: "!Sie benutzen eine extrem alte Version des Internet Explorers ... gerade so hässlich angezeigt" wiederlich hässlich ist dein roter Warnkasten. Ansonsten wird diese Seite abgesehen von der fehlenden <li> Formatierung & Einrückung einwandfrei angezeigt. Und ein Browser ist immer so sicher, wie seine Sicherheitseinstellungen und dem Umfang der Rechte des Benutzerkontos unter dem der Browser läuft. Brain 1.0 ist das Wesentliche ;-) Bitte löse die Rechenaufgabe. Dies dient als Spam-Schutz. -> Browser Sicherheitseinstellungen
  • Jens schreibt am 13.02.11 um 05:05 Uhr: Klasse Tutorial! Einfach verständlich und gut geschrieben. Hat mir heute bei bei Lösung des Umgangs mit "Gierigen Ausdrücken" geholfen. Viele Grüße aus Freiburg.
  • ArChOn schreibt am 10.02.11 um 19:39 Uhr: Super Tutorial zum Thema... hat mir gut geholfen mich wieder in das Thema einzuleben ;o)
  • Fitzi schreibt am 26.01.11 um 14:50 Uhr: wow, endlich mal ein Tutorial das die Regex-Regeln so erklärt, dass man's auch versteht :D auch von mir ein fettes Danke :D
  • MJ schreibt am 24.01.11 um 10:58 Uhr: Voll Fett Daniel Danke!
  • Ressaw schreibt am 09.12.10 um 19:54 Uhr: Toller Beitrag, hilft mir hoffentlich, sowas hab ich gesucht! Danke :)
  • Niklas schreibt am 30.11.10 um 11:20 Uhr: (?<=0)\d{3}(?=0) der Ausdruck ist für das geforderte Ergebnis nicht zulässig, da auch z.b 010 gematcht wird, richtig wäre z.b (?<=0)[1-9]{3}(?=0)
  • Falk schreibt am 22.11.10 um 13:17 Uhr: Tolles, sehr anschauliches Tutorial! Vielen Dank!
  • Jens schreibt am 13.11.10 um 17:07 Uhr: Hallo, danke für den leicht zu verstehenden Artikel, hat mir direkt weitergeholfen!
  • sky schreibt am 29.10.10 um 22:48 Uhr: Endlich ein vernünftiges Tutorial, sehr gut gelungen!!!
  • Ingo schreibt am 04.10.10 um 16:59 Uhr: Hallo, habe die Seite gerade über ein Forum gefunden und muss sagen, gefällt mir sehr gut. Sind echt nützliche Beispiele dabei und vor allem welche, wie man es nicht macht! Tolle Seite, nicht nur für Anfänger ;-)
  • Alex schreibt am 20.09.10 um 13:04 Uhr: Hi, Tolles Material... Ist es möglich ein solchen Ausdruck zu schreiben, wo ein Text nach ":", ";" und "." z.B, segmentiert wird, wobei er trotzdem die Trennungszeichen jeweils behaltet '.<br>', ':<br>', '!<br>' oder ';<br>' ABER jedoch nicht segmentiert nach Kapiteln, Datum und Abkürzungen mit einem oder zwei Pünkte? (u.a., bzw., z.B., 1., 2., 3., ...) Grüße
  • leito schreibt am 12.09.10 um 00:12 Uhr: Super! Das habe ich gesucht, danke sehr ;D
  • Danio schreibt am 10.09.10 um 15:51 Uhr: Vielen Dank für das anschauliche und gut strukturierte Tutorial. Die zu akademischen Lehransätze diesbezüglich sind sicherlich bemerkenswert, jedoch liebe ich einfache Dinge wie Dein Tutorial (Back to simplicity). Grüsse aus der Schweiz/Zug
  • leTon schreibt am 10.09.10 um 14:40 Uhr: Hi, ich möchte endlich was über reguläre Ausdrücke lernen und würde gern Dein Tutorial durchspielen. Leider führt bereits das erste Beispiel nicht zum gewünschten Ergebnis. Es heisst: "Wir prüfen, ob unsere Eingabe eine Schulnote ist." Wenn ich das mit if(preg_match('/[123456]/' , $suche)) programmiere gibt "2" true, genauso wie "2auto". Das nervt mich ehrlich gesagt, weil es so klingt, als ob diese Prüfung eine Schulnote checkt. Wo liegt der Fehler? Vielen Dank
  • Florian schreibt am 21.08.10 um 14:36 Uhr: Super Tutorial. Ich versuche gerade etwas zum Gleichungen Lösen zu programmieren und da war dieses Tutorial eine große Hilfe! Danke!
  • Manü schreibt am 19.08.10 um 15:47 Uhr: Ahoi, ich heute mal in die Verlegenheit mich mit RegEx beschäftigen zu müssen und nach einigen anderen seiten hatte mich dann dein Tut hier, von 0 auf 80 gebracht ;)
  • adolf schreibt am 17.08.10 um 15:29 Uhr: hui manchmal treffen nicht die fälle in THE Regex Coach ein die man hier durchgespielt hat, trotzdem danke für sell tutorial!
  • der dirk schreibt am 30.07.10 um 14:56 Uhr: REGionalEXpress, haha wie passend :D danke für das tut!
  • leth schreibt am 06.07.10 um 13:38 Uhr: Vielen Dank für das sehr gute Tutorial. Ich habe mich mal etwas mit RegExpr beschäftigt, aber nach wie vor Probleme damit, maskierte Anführungszeichen innerhalb von Texten die wiederum von Anführungszeichen begrenzt werden, zuzulassen. Google konnte mir da bisher nicht weiterhelfen, wahrscheinlich verwende ich nur die falschen Suchbegriffe. Aber vielleicht kannst Du Dein Tutorial entsprechend ergänzen :-) Cu leth
  • cavalorn schreibt am 25.06.10 um 19:31 Uhr: Ich sitze gerade im ICE (NICHT Regionalexpress) und ziehe mir den Artikel rein. Like!
  • @Gleisbauer schreibt am 20.06.10 um 21:06 Uhr: Was ist, wenn auf unserem Bahnhof jetzt angebaut wird? Sagen wir, er wird auf 12 Gleise erweitert: [1-12] --> findet nur die Ziffern 1-1 oder die 2, also 1 oder 2. Liest man weiter: [1-9][ab] Will heißen: Eine Zahl 1-9 gefolgt von einem Buchstaben a oder b. Genauso kann man einer Ziffer eine Ziffer folgen lassen, also [1][2] verlangt eine 1 gefolgt von einer von 2, also 12 Gibts jetz alle Gleise von 1 bis 12, dann können es einstellige oder zweistellige Zahlen sein. [1-9][1-2]? --> Damit ist zwar die 11 oder 12 möglich, aber auch 21 bis hin zu 92. [1-9] oder [1][1-2] --> gibt eine Ziffer aus 1-9 oder eine 12 bzw 12 Veroderung mit dem Pipe wie oben dargestellt führt zu ([1-9]) | ([1][1-2]) --> Zahlen zwischen 1-12, voilá Die runden Klammern sind jetzt nur für den Leser, um die optische Einheit der beiden Alternativen zu verdeutlichen.
  • Kristian schreibt am 19.06.10 um 18:36 Uhr: Es kommt ab und an vor das ich mich RegEx beschäftige und bei jedem neuem Ausdruck den ich benötige, fussel ich mich von vorne mit RegEx durch... hier kommt mir dein super erklärtes Tutorial immer wieder zu gute. Danke für die anschaulich und unterhaltende Erklärungsweise!
  • RegExNoob schreibt am 16.06.10 um 10:20 Uhr: Vielen, vielen Dank für dieses super Tut. Pädagogisch wertvoll und angenehm locker wie idiotensicher erklärt ;)
  • Gleisbauer schreibt am 20.05.10 um 16:49 Uhr: Super erklärt. Ich konnte allerdings keine Lösung für das oben erwähnte 12 Gleise - Problem finden. Wie muss z.B der Ausdruck lauten, wenn nur eine 10-stellige Zahl zugelassen wird, die mit 400-412 oder 347 anfangen darf? DuG
  • @-Zeichen schreibt am 29.04.10 um 09:06 Uhr: Hey Daniel, geniale Erklärung. Hast mir gerade den Tag gerettet. :-) Viele Grüße aus Bayern.
  • Tom schreibt am 02.04.10 um 07:18 Uhr: Klasse Anleitung! Damit hat selbst ein Journalist wie ich mal etwas verstanden. DANKE!
  • Martin schreibt am 17.03.10 um 13:08 Uhr: Darf ich eine Frage stellen? es gibt einen String, der sich durch Hochkomma begrenzt und mit Kommata getrennt beliebig oft wiederholen darf, z.b. 'd1' oder 'd1','d2' oder 'd1','d2','d3' etc. Die Gültigkeit versuche ich hiermit zu ermitteln: /('[\w]+')(\,\1)*/. Allerdings behauptet er, auch 'd1','d1 (also ohne beendendes Hochkomma) oder 'd'', (also Komma obwohl kein folgender Text) sei gültig... wo ist der Haken? Danke schon mal!
  • Carsten schreibt am 17.03.10 um 09:56 Uhr: Bis gerade eben hatte ich 0 Plan von regulären ausdrücken, aber jetzt erscheint mir endlich ein helles Licht am ende des Tunnels :) Danke für das Top-Tutorial.
  • Michael schreibt am 16.03.10 um 11:35 Uhr: @Claus: Danke, es stimmt zwar nicht, hat mich aber auf den richtigen Weg gebracht. Die Lösung lautet: ([15](/\d{6}\-)|([26]/\d{6}\+))\d{6}
  • Claus schreibt am 14.03.10 um 18:12 Uhr: @Michael: versuchs mal mit folgendem: (?([15])[15]/\d{6}-|[26]/\d{6}\+)\d{6} @Daniel: Danke für das Tut
  • andi schreibt am 11.03.10 um 12:29 Uhr: @ Stefan -> du kannst wenn du die Datei als "Single-Line" druchläufst ein "$" ans ende des Regulären Ausdrucks stellen, das bedeutet, dass die Zeile dort zuende ist. Fazit: $ = Ende der Zeile. Wenn du jedoch den Regulären Ausdruck auf die gesammte Datei loslässt wird dir das $ nicht weiterhelfen, da solltest du evtl sowas wie [^\n\r] anwenden. Gruß Andi
  • Michael schreibt am 03.03.10 um 13:32 Uhr: Danke für das Tutorial - ich bin wahrlich kein Spezialist für reguläre Ausdrücke, aber das ist ganz gut hier. Kleines Problem: Ich habe folgenden Ausdruck: [1256]/[0-9]{6}[+-][0-9]{6} - und dann soll noch die Einschränkung gelten: Wenn an der ersten Stelle 1 oder 5 steht, dann soll an der 9. Stelle "-", sonst "+" stehen. Lässt sich das machen?
  • WebSmurf schreibt am 10.02.10 um 15:54 Uhr: Habe gelegentlich beruflich und privat mit RegExen zu tun. Nicht genug um fit darin zu sein aber oft genug um graue Haare bei der Lösungssuche zu bekommen. Daher kommt das tolle Tutorial immer wieder zum Zuge um mein eingerostetes Wissen auf Vordermann zu bringen. -Danke-
  • Stefan schreibt am 09.02.10 um 08:55 Uhr: Sehr gut und nun (.+) nimmt leider auch am Ende das CR vom CRLF mit. Wir kann ich den noch ausschließen?
  • Thorsten schreibt am 02.02.10 um 13:16 Uhr: Tolle Einführung in RegExp. Vielen Dank!
  • Dr.Miles schreibt am 01.02.10 um 23:38 Uhr: Hey super Tutorial, hat mir auch sehr weitergeholfen. Selbst heute wenn ich manchmal noch eine Frage habe greife ich manchmal auf dieses Tut zurück. Ist auch nicht so trocken geschrieben wie viele andere Texte, mir gefällt auch, dass nicht nur die förmlich korrekte Schreibweise eingesetzt wird, sondern auch die in Programmierkreisen verbreitete Umgangssprache wie beispielsweise der Ausdruck "frisst" etwas. Das habe ich bisher noch nicht so oft gesehen.
  • M.Lerjen schreibt am 03.01.10 um 22:29 Uhr: Danke für die Einführung! Anstelle des RegEx-Coach hat mir schliesslich der <a href=http://regexp-evaluator.de/evaluator/ target=neu>RegExp-Evaluator</a> gute Dienste geleistet.
  • Peter Schleif schreibt am 03.01.10 um 15:05 Uhr: Hallo Daniel. Ich habe vor langer Zeit u.a. mit deiner tollen Seite reguläre Ausdrücke gelernt und verdanke Dir somit den Einstieg in diese Technik. Als Einführung ist deine Seite genau das Richtige. Auch heute schaue ich noch ab und zu vorbei; ist immer wieder interessant. Den neuen Look und das Gästebuch habe ich leider jetzt erst entdeckt. Sieht gut aus. Muss ich gleich mal ausprobieren. Peter.
  • Jonas schreibt am 27.12.09 um 20:45 Uhr: Hallo! Hatte vorher keine Ahnung, jetzt ist es ausreichend für InDesign GREPs (Anwendungsgebiet!!:) - danke!
  • rummi schreibt am 26.12.09 um 23:42 Uhr: Vielen Dank!
  • Peter schreibt am 24.12.09 um 09:20 Uhr: Hallo. HÄZZLICH. GR.
  • yoyo schreibt am 24.12.09 um 08:45 Uhr: yoyo sattes tut,n1
  • Rumblefish schreibt am 16.12.09 um 20:31 Uhr: Eher selten habe ich mit regulären Ausdrücken zu tun - aber das hier ist ganz klar der Text, der mir die Lösungen zu meinen RegEx - Problemen liefert !
  • KleinierDelphiin schreibt am 15.12.09 um 13:28 Uhr: Super erklärung.. und das beste mal mit beispielen.. das vermisse ich auf anderen Seite, ich persönlich lerne nur durch sehende Logik.. also wass passiert dann und dann.. gibt ja viele möglichekiten...
  • Bernd das Brot schreibt am 13.12.09 um 13:42 Uhr: Super erklärung, welche mich hoffentlich durch die Prüfung bringt:) Vielen Dank!
  • Horttcore schreibt am 10.12.09 um 15:05 Uhr: Netter Beitrag, ich habe immer viel Probleme mit RegEx aber ist es sehr schön erklärt. Gruss aus Saarbrücken
Kommentar schreiben
  • Bugs in AGTL bitte hier melden.
    Please report any bugs in AGTL here.
  • Wer eine Antwort erwartet, sollte eine echte E-Mail-Adresse angeben.
    If you expect a reply from me, please provide a working e-mail address.
  • Ich kann keine individuelle Problemlösung zu Websicherheit oder regulären Ausdrücken geben!
Name:
Website: http:// optional
E-Mail: wird nicht veröffentlich
Spam-Check: 20 pl us 7 ist gleich