Strings als reguläre Ausdrücke

(Auszug aus "Reguläre Ausdrücke" von Jeffrey E. F. Friedl)

In den meisten Sprachen außer Perl, awk und sed bekommt die Regex-Maschine die regulären Ausdrücke in String-Form vorgesetzt – oft ist das ein literaler String wie beispielsweise "^From:(.*)". Was dabei viele anfänglich verwirrt, ist die Tatsache, dass auch Strings ihre Metazeichen haben, die sich von denen der regulären Ausdrücke unterscheiden.

In jeder Sprache haben die literalen Strings ihre eigenen Metazeichen. Manche Sprachen haben sogar verschiedene Typen von literalen Strings; es kann also gar keine Regel geben, die überall anwendbar ist. Dennoch sind die Prinzipien überall etwa die gleichen. Bei den meisten Sprachen sind Sequenzen wie \t, \\ und \x2A zulässig, aus denen beim Aufbau des Strings ein einzelnes Zeichen wird. Für die regulären Ausdrücke ergibt sich daraus in den meisten Fällen, dass die Backslashes, die in der Regex vorkommen, verdoppelt werden müssen. Für die Regex ˹\n˼ muss beispielsweise "\\n" geschrieben werden.

Wenn Sie den zusätzlichen Backslash im String vergessen und nur "\n" eingeben, wird daraus bei den meisten Sprachen ˹NL˼, was in den meisten Fällen gleich interpretiert wird wie ˹\n˼. Das kann dennoch Probleme bereiten: Wenn Sie den Modus »Freie Form« mit dem /x-Modifikator oder einem Äquivalent verwenden, wird ˹NL˼ zu einer leeren Regex, ˹\n˼ passt dagegen immer noch auf ein Newline. In der folgenden Tabelle werden ein paar Beispiele mit \t und \x2A gezeigt (2A ist der hexadezimale ASCII-Code für ›*‹). Die zwei letzten Spalten zeigen, was passieren kann, wenn man aus Versehen nur einen Backslash angibt.

Tabelle: Beispiele für literale Strings.

Literaler String "[\t\x2A]" "[\\t\\x2A]" "\t\x2A" "\\t\\x2A"
Wert des Strings [TAB*] [\t\x2A] TAB* \t\x2A
Als Regex interpretiert ˹[TAB*]˼ ˹[\t\x2A]˼ ˹TAB*˼ ˹\t\x2A˼
Passt auf Tab oder Stern Tab oder Stern Jede Anzahl von Tabs Ein Tab, dann ein Stern
Im /x-Modus Tab oder Stern Tab oder Stern Fehler Ein Tab, dann ein Stern

In jeder Sprache verhalten sich die literalen Strings leicht unterschiedlich, aber manche sind sehr verschieden, weil in ihnen ›\‹ kein Metazeichen ist. Die literalen Strings in VB.NET beispielsweise kennen nur ein einziges Metazeichen, das Anführungszeichen. In den nächsten Abschnitten werden die verschiedenen Aspekte von Strings in den einzelnen Sprachen behandelt. Sie sollten dabei folgende Frage im Hinterkopf behalten: »Was bekommt die Regex-Maschine nach der String-Interpretation der Programmiersprache zu sehen?«

Strings in Java

Die literalen Strings von Java haben Sie schon in der Einleitung kennengelernt: Sie werden durch Anführungszeichen eingefasst, und der Backslash ist ein Metazeichen. Java kennt die typischen Backslash-Sequenzen wie ›\t‹ (Tab), ›\n‹ (Newline), ›\\‹ (literaler Backslash) usw. Eine unbekannte Backslash-Sequenz erzeugt einen Fehler.

Strings in VB.NET

In VB.NET werden Strings ebenfalls durch Anführungszeichen begrenzt, aber der Backslash ist hier kein Metazeichen. VB.NET kennt genau ein Metazeichen: Ein verdoppeltes Anführungszeichen innerhalb eines literalen Strings erzeugt ein einzelnes Anführungszeichen im Wert des Strings. Zum Beispiel wird aus "Er sagte ""hallo""\." der String-Wert ˹Er sagte "hallo".\˼

Strings in C#

Alle Sprachen innerhalb des .NET-Frameworks von Microsoft verwenden die gleiche Regex-Maschine, aber jede Sprache hat ihre eigenen Regeln, wie sie die Strings behandelt, die später als reguläre Ausdrücke interpretiert werden. Visual Basic hat nur eine einfache Art von literalen Strings. In C# gibt es zwei Typen von literalen Strings.

Zum einen gibt es in C# die normalen Strings in Anführungszeichen wie in der Einführung zu diesem Abschnitt, außer dass ein Anführungszeichen durch "" und nicht durch das üblichere \" eingefügt wird. Außerdem gibt es sogenannte »Verbatim-Strings« mit der Notation @"...". In diesen werden keine Backslash-Sequenzen erkannt, wiederum mit Ausnahme des Anführungszeichens, das man mit \" einfügen kann. Das Beispiel ˹\t\x2A˼ kann man also entweder "\\t\\x2A" oder mit einem Verbatim-String @"\t\x2A" schreiben. Für die meisten regulären Ausdrücke sind Verbatim-Strings einfacher.

Strings in PHP

Auch in PHP gibt es zwei Arten von Strings, aber beide unterscheiden sich von denen von C# . Bei den Strings in Anführungszeichen (»Gänsefüßchen«) gibt es die üblichen Backslash-Sequenzen wie ›\n‹, außerdem werden aber Variablen interpoliert, wie wir das von Perl kennen. Mehr noch, mit der Sequenz {...} wird das Resultat des PHP-Codestücks, das zwischen den geschweiften Klammern steht, in den String eingefügt.

Wegen dieser Eigenschaften braucht man in PHP bei Strings in Anführungszeichen eine Menge Backslashes, wenn man damit reguläre Ausdrücke schreibt. Bei Java oder C# ist eine unbekannte Backslash-Sequenz einfach ein Fehler, in PHP wird die unbekannte Sequenz als zwei Zeichen in den Wert des Strings übernommen. In PHP ist \t ein String-Metazeichen, man muss also "\\t" schreiben, damit man die Regex ˹\t˼ erhält, aber mit "\w" erhält man den regulären Ausdruck ˹\w˼, weil \w kein String-Metazeichen, sondern eine unbekannte Backslash-Sequenz ist. Das verringert die Anzahl der erforderlichen Backslashes, ist aber nicht immer einfach zu verstehen.

Deshalb kennt PHP auch eine einfachere Art von literalen Strings, die Strings in Hochkommas. Diese ähneln den Strings von VB.NET oder den @"..."-Strings von C#, aber hier kann man mit \' ein Hochkomma in den String einfügen, und mit einem \\ vor dem abschließenden Hochkomma kann man einen String erzeugen, der mit einem Backslash endet. Alle anderen Zeichen (auch der Backslash) sind normale Zeichen und werden unverändert in den String übernommen. Aus '\t\x2A' wird so ganz einfach ˹\t\x2A˼, und deshalb wird man in PHP normalerweise die Hochkomma-Strings für reguläre Ausdrücke verwenden.

Strings in Hochkommas in PHP werden später genauer behandelt.

Strings in Python

In Python gibt es eine ganze Reihe von verschiedenen Stringtypen. Man kann Anführungszeichen oder Hochkommas benutzen, und im Gegensatz zu PHP besteht zwischen diesen kein Unterschied. In Python gibt es dafür die »Dreifach-Strings« mit der Notation '''...''' bzw. """...""", die sich über mehrere Zeilen erstrecken können. Bei allen vier Typen gibt es die Backslash-Sequenzen vom \n-Typus mit der gleichen Konvention wie in PHP: Bei unbekannten Backslash-Sequenzen wird der Backslash in den Wert des Strings übernommen (im Gegensatz zu Java und C#, wo unbekannte Backslash-Sequenzen Fehler sind).

Wie in PHP und C# gibt es auch in Python eine einfachere Art von literalen Strings, die in Python – ganz ähnlich wie bei der @"..."-Notation von C# – durch ein vorangestelltes ›r‹ markiert werden. In Python kann man vor alle vier Arten von Strings ein ›r‹ (für raw, roh) setzen: r"\t\x2A" ergibt ˹\t\x2A˼. In diesen Strings werden jedoch alle Backslashes als normale Zeichen angesehen, r"Er sagte \"hallo\"\." ergibt also ˹Er sagte \"hallo\"\.˼. Das ist im Zusammenhang mit regulären Ausdrücken normalerweise unproblematisch, weil im Regex-Dialekt von Python ˹\"˼ und ˹"˼ gleich behandelt werden; man kann aber auch einfach auf andere Begrenzungszeichen ausweichen: r'Er sagte "hallo"\.'

Strings in Tcl

In Tcl gibt es im Unterschied zu allen bisher behandelten Sprachen keine eigentlichen literalen Strings. Befehlszeilen werden hier in »Wörter« aufgeteilt, und die Tcl-Befehle können diese Wörter als Variablen, Strings, reguläre Ausdrücke oder was auch immer interpretieren. Beim Aufteilen einer Befehlszeile in Wörter werden bestimmte Backslash-Sequenzen wie \n erkannt und durch das entsprechende Zeichen ersetzt; die Backslashes vor unbekannten Backslash-Sequenzen werden schlicht ignoriert. Man kann Wörter in Anführungszeichen schreiben, das ist aber nur erforderlich, wenn sie Whitespace enthalten.

Es gibt in Tcl auch eine Art von nackten literalen Strings, die den r'...'-Strings von Python ähneln. Hier werden aber geschweifte Klammern benutzt. Innerhalb von r'...' wird alles außer der Backslash-Newline-Kombination ohne Änderung in den String-Wert übernommen, man kann also {\t\x2A} für ˹\t\x2A˼ verwenden.

Innerhalb der geschweiften Klammern sind weitere geschweifte Klammerpaare erlaubt. Einzelne öffnende oder schließende geschweifte Klammern müssen mit einem Backslash maskiert werden, und dieser Backslash bleibt im String erhalten.

Regex-Literale in Perl

In den bisherigen Perl-Beispielen in diesem Buch waren alle regulären Ausdrücke Literale (»Regex-Literale«). Man kann sie aber tatsächlich auch in String-Form angeben. Zum Beispiel kann man

$str =~ m/(\w+)/;

auch so schreiben:

$regex = '(\w+)';
$str =~ $regex;

oder vielleicht auch so:

$regex = "(\\w+)";
$str =~ $regex;

(Ein String als Regex kann allerdings unter Umständen sehr viel ineffizienter sein).

Perl kennt bei Regex-Literalen Features, die die Regex-Maschine selbst nicht kennt:

  • Variablen werden interpoliert (d.h., statt des Namens der Variablen wird deren Wert in die Regex eingesetzt).
  • Literaler Text wird mit ˹\Q...\E˼ unterstützt.
  • Es gibt das Konstrukt \N{Name}, mit dem man ein Zeichen mit seinem offiziellen Unicode-Namen eingeben kann. Zum Beispiel passt ˹\N{INVERTED EXCLAMATION MARK}Hola!˼ auf ›¡Hola!‹.

In Perl wird eine literale Regex wie eine besondere Art von String verarbeitet. Die genannten Features gibt es in der Tat auch bei ganz gewöhnlichen Strings in Anführungszeichen. Der springende Punkt ist, dass dies nicht Features der Regex-Maschine sind. Der größte Teil der regulären Ausdrücke tritt tatsächlich als Regex-Literal auf, daher denken die meisten Benutzer, dass ˹\Q...\E˼ zum Regex-Dialekt von Perl gehöre. Wenn man aber beispielsweise reguläre Ausdrücke aus einer Konfigurationsdatei einliest (oder von der Befehlszeile), dann muss man genau wissen, zu welchem Teil der Programmiersprache ein Feature gehört.

Unter Perl gibt es ab Regex-Operanden und Regex-Literale mehr zu diesem Thema.

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema Reguläre Ausdrücke bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:
   

Copyright der deutschen Ausgabe © 2008 by O’Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Reguläre Ausdrücke" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstr. 81, 50670 Köln