Nackten Text in HTML verwandeln

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

Wir schreiben ein kleines Programm, das normalen Text in HTML verwandelt. Es ist schwierig, ein allgemeines Programm für diesen Zweck zu schreiben, das jeden Wunsch abdeckt; hier schreiben wir eine einfache Version für Lernzwecke.

In allen bisherigen Beispielen haben wir reguläre Ausdrücke zeilenweise auf Text angewendet. Für dieses Problem ist es viel einfacher und auch spannender, wenn wir den ganzen Text als langen String in einer Variablen zur Verfügung haben. In Perl geht das wie folgt:

undef $/;
$text = <>;
# »Ganze Datei«-Modus aktivieren.
# Die gesamte auf der Befehlszeile angegebene Datei einlesen.

Wenn unsere Beispieldatei lediglich die folgenden drei Zeilen enthält:

Eine Beispieldatei.
Mit drei Zeilen.
Das ist alles.

Dann hat die Variable $text nach dem Einlesen folgenden Wert:

Eine Beispieldatei.NLMit drei Zeilen.NLDas ist alles.NL

Sie kann aber auch, je nach dem verwendeten Betriebssystem, folgenden Wert haben:

Eine Beispieldatei.CR NLMit drei Zeilen.CR NLDas ist alles.CR NL

Die meisten Systeme verwenden das Newline als Zeilenendezeichen, manche (Windows) benutzen jedoch eine Kombination von Carriage Return und Newline. Wir konzipieren unser Programm so, dass es mit beiden funktioniert.

Sonderbehandlung für bestimmte Zeichen

Zuallererst müssen wir die Zeichen ›&‹, ›<‹ und ›>‹ »unschädlich« machen, indem wir sie, wie in HTML vorgesehen, als ›&amp;‹, ›&lt‹ und ›&gt‹ codieren. Diese Zeichen haben in HTML eine besondere Funktion. Wenn wir sie nicht codierten, käme nicht selten Buchstabensalat auf dem Bildschirm an.

$text =~ s/&/&amp;/g;
$text =~ s/</&lt;/g; 
$text =~ s/>/&gt;/g;
# Die HTML-Zeichen ...
# ... &, < und > ...
# ... unschädlich machen.

Hier verwenden wir wieder /g, damit alle in der Datei vorkommenden Zeichen codiert werden. Es ist wichtig, dass & zuerst drankommt, weil in den Ersatztexten aller drei das Zeichen ›&‹ wiederum vorkommt.

Text in Abschnitte unterteilen

Als Nächstes teilen wir den Text in Abschnitte auf, indem wir das HTML-Tag <p> zwischen den Abschnitten einfügen. In normalem, nacktem Text sind Abschnitte durch Leerzeilen voneinander getrennt. Es gibt verschiedene Arten, nach Leerzeilen zu suchen. Wir könnten versucht sein, so etwas zu verwenden:

$text =~ s/^$/<p>/g;

Wir suchen nach einem Zeilenanfang, auf den unmittelbar ein Zeilenende folgt. Bei einem Werkzeug wie egrep, das Texte immer Zeile für Zeile einliest, würde das auch funktionieren, wie Sie in Lösung 1 gesehen haben. Beim E-Mail-Beispiel weiter vorn hätte das auch mit Perl funktioniert, weil wir da sichergestellt haben, dass der Suchstring immer nur eine logische Zeile der E-Mail enthält.

Wie ich aber in der Anmerkung unter Ein kleines Mail-Programm erwähnt habe, beziehen sich ˹^˼ und ˹$˼ üblicherweise nicht auf logische Zeilenanfänge und -enden, sondern auf die Positionen am Anfang und am Ende des gesamten abgesuchten Strings. (Anmerkung: Bei ˹$˼ ist es meist noch etwas komplizierter, aber das spielt im vorliegenden Beispiel keine Rolle. Mehr dazu erfahren Sie im Abschnitt zu den Zeilenankern.) Wir haben hier aber mehrere logische Zeilen in einem einzigen String und müssen also etwas anderes finden.

Bei den meisten Programmiersprachen mit regulären Ausdrücken gibt es glücklicherweise einen Mehrzeilenmodus, in dem sich ˹^˼ und ˹$˼ auf logische Zeilenanfänge und -enden innerhalb eines Strings beziehen. In Perl benutzt man dafür den Modifikator /m:

$text =~ s/^$/<p>/mg;

Beachten Sie, wie die Modifikatoren /m und /g kombiniert werden (bei mehreren Modifikatoren spielt die Reihenfolge keine Rolle). Wie das in anderen Sprachen gemacht wird, erfahren Sie unter Features und Dialekte.

Wenn unsere Variable $text zum Beispiel ›...Kapitel.NLNLWenn...‹ enthält, wird daraus wie gewünscht ›...Kapitel.NL<p>NLWenn...‹.

Auch das funktioniert aber nicht, wenn die »Leer«-Zeile Leerzeichen oder anderen Whitespace enthält. Wir können mit ˹^*$˼ Leerzeichen zulassen oder mit ˹^[\t\r]*$˼ Leerzeichen, Tabs und die Carriage-Return-Zeichen, die manche Systeme vor dem Newline haben. Diese Ausdrücke sind aber grundsätzlich verschieden vom bloßen ˹^$˼, weil sie auf wirklichen Text passen und nicht nur auf eine Position im String. Weil wir aber diese Whitespace-Zeichen in diesem Fall nicht benötigen (und sie durch das <p>-Tag ersetzen können), ist uns das egal.

Wenn Sie sich das Metazeichen ˹\s˼ vom Abschnitt Whitespace mit \s vergegenwärtigen, könnten Sie auf die Idee kommen, ˹^\s*$˼ zu verwenden. Wenn wir ˹\s˼, das auch auf Newlines passt, statt ˹[\t\r]˼ verwenden, ändert sich aber die Bedeutung der Regex. Sie passt jetzt nicht nur auf »Zeilen, die Whitespace enthalten oder ganz leer sind«, sondern auch auf »Folgen von Zeilen, die Whitespace enthalten oder ganz leer sind«. Wenn wir also aufeinanderfolgende Leerzeilen haben, werden diese von einem einzigen ˹^\s*$˼ erkannt und durch ein einziges <p> ersetzt. Das ist in unserem Fall ganz gut: Wir bekämen sonst aufeinanderfolgende <p>-Tags ohne Text dazwischen. Wenn wir in der Variablen $text den String

... dazwischen.NLNLNLTABNLWenn ...

haben und die folgende Substitution darauf anwenden:

$text =~ s/^[ \t\r]*$/<p>/mg;

dann erhalten wir:

... dazwischen.NL<p>NL<p>NL<p>NLWenn ...

Wenn wir aber

$text =~ s/^\s*$/<p>/mg;

verwenden, erhalten wir das Gewünschte:

... dazwischen.NL<p>NLWenn ...

Wir werden also im endgültigen Programm ˹^\s*$˼ verwenden.

E-Mail-Adressen »verlinken«

Im nächsten Schritt soll unser Text-zu-HTML-Konverter lernen, E-Mail-Adressen zu erkennen und sie in »Mailto«-Links umzuwandeln. Eine Adresse wie »jfriedl@oreilly.com« soll in <ahref="mailto:jfriedl@oreilly.com">jfriedl@oreilly.com</a> verwandelt werden.

Dieser Wunsch – E-Mail-Adressen mit einem regulären Ausdruck zu erkennen – taucht in der Praxis sehr oft auf. Die exakte Spezifikation für eine E-Mail-Adresse ist sehr kompliziert, und es ist entsprechend schwierig, sie in einen regulären Ausdruck umzusetzen. Wenn wir uns aber mit einer Lösung zufriedengeben, die die üblichen Formen von E-Mail-Adressen erkennt, wird es schnell viel einfacher. Grundsätzlich haben E-Mail-Adressen die Form »username@hostname«. Wir werden die Unterausdrücke für die beiden Teile später formulieren, aber insgesamt werden wir die E-Mail-Adressen so in »Mailto«-Links verwandeln:

$text =~ s/\b(username­regex\@hostname­regex)\b/<a href="mailto:$1">$1<\/a>/g;

Zunächst habe ich die zwei Backslashes hervorgehoben: einen in der Regex (›\@‹) und einen gegen Ende des Ersatztextes. Die Backslashes werden aus unterschiedlichen Gründen gebraucht. Die erste Art von Backslashes wird etwas später besprochen, im Moment genügt es zu wissen, dass in Perl die @-Zeichen in einer Regex geschützt werden müssen.

Der Backslash vor dem ›/‹ im Ersatztext ist dagegen leicht verständlich. Beim Substitutionsoperator von Perl werden Regex, Ersatztext und gegebenenfalls vorhandene Modifikatoren durch Schrägstriche begrenzt: s/Regex/Ersatztext/Modifikatoren. Wenn einer der Teile selbst einen Schrägstrich enthält, müssen wir diesen mit einem Backslash maskieren, sodass Perl merkt, dass es sich nicht um einen der Begrenzungsstriche handelt. Wenn wir also ein <a> im Ersatztext wollen, müssen wir dafür <\/a> schreiben.

Das funktioniert zwar, sieht aber nicht so gut aus. In Perl gibt es auch eine andere Möglichkeit: Man kann die Art der Begrenzer selbst wählen, z.B. s!Regex!Ersatztext!Modifikatoren oder s{Regex}{Ersatztext}Modifikatoren. Bei beiden Beispielen kommen die Begrenzungszeichen weder in der Regex noch im Ersatztext vor, wir brauchen also kein Zeichen zu maskieren. Beim zweiten Beispiel werden Regex und Ersatztext eingeklammert. Diese Form werden wir ab jetzt häufiger benutzen.

Beachten Sie, dass die gesamte Adresse in ˹\b...\b˼ eingepackt ist. Mit den Wortgrenzen werden Treffer innerhalb von Wörtern vermieden, zum Beispiel ›jfriedl@oreilly.compiler‹. Solcher Unsinn kommt in normalen Texten zwar kaum vor, aber wenn wir uns mit zwei kleinen Metazeichen dagegen absichern können, kostet uns das wenig. Beachten Sie außerdem, dass der ganze Adressteil eingeklammert ist. Hier werden die einfangenden Klammern gebraucht, weil im Ersatztext der von diesen Klammern abgespeicherte Text verwendet wird: ›<ahref="mailto:$1">$1</a>‹.

Username und Hostname

Wir wenden uns nun den eigentlichen Bestandteilen einer E-Mail-Adresse zu und entwickeln reguläre Ausdrücke für Username und Hostname. Hostnamen wie beispielsweise regex.info und www.oreilly.com bestehen aus durch Punkte abgetrennten Teilen, von denen der letzte ›com‹, ›edu‹, ›info‹, ›de‹ usw. lautet. Eine sehr simple Regex für eine ganze E-Mail-Adresse wäre zum Beispiel ˹\w+\@\w+(\.\w+)+˼, das lässt für den Usernamen und jeden Teil des Hostnamens ein beliebiges »Wort« zu, nämlich ˹\w+˼. Für die Praxis taugt das kaum. Usernamen enthalten oft Punkte und Bindestriche (wenn auch höchst selten am Anfang). Statt ˹\w+˼ nehmen wir daher besser ˹\w[-.\w]*˼. Ein damit erkannter Username beginnt mit einem ˹\w˼-Zeichen, lässt aber bei den folgenden Zeichen auch Punkte und Bindestriche zu. (Beachten Sie, dass der Bindestrich als erstes Zeichen in der Zeichenklasse angegeben wird, damit er als literaler Bindestrich und nicht als Metazeichen für einen Bereich wie ›a-z‹ interpretiert wird. Der Bereich ›.-\w‹ enthält je nach Implementation und Zeichensatz eine ganze Menge Sonderzeichen.)

Beim Hostnamen-Teil wird es komplizierter, weil die Punkte hier Trennzeichen sind. Das bedeutet, dass zwischen den Punkten etwas vorkommen muss, das sie voneinander abtrennen. Deshalb haben wir sogar im ersten, einfachen Ansatz ˹\w+(\.\w+)+˼ statt nur ˹[\w.]+˼ genommen. Die letztere Regex ließe auch Hostnamen wie ›..x..‹ zu, aber auch die erste erkennt Dinge wie ›Drehmoment 117Nm@6.750/min‹; wir müssen uns also etwas präziser ausdrücken.

Wir könnten beispielsweise aufzählen, was es beim letzten Element für zulässige Möglichkeiten gibt, also so etwas wie ˹\w+(\.\w+)*\.(com|edu|info)˼. (Diese Liste müsste eigentlich com|edu|gov|int|mil|net|org|biz|info|name|museum|coop|aero|[a-z][a-z] umfassen, aber ich möchte die Beispiele kurzhalten.) Das erste Element muss also auf ˹\w+˼ passen, weitere gleich aufgebaute Elemente werden mit ˹\.\w+˼ erlaubt, und am Ende muss einer der aufgezählten Strings auftreten.

In Wirklichkeit ist ˹\w˼ nicht ganz das Richtige. Damit werden ASCII-Buchstaben und Ziffern zugelassen. Je nach System und Einstellung erlaubt ˹\w˼ aber auch Nicht-ASCII-Zeichen wie à, ç , Ξ oder Æ, bei den meisten Regex-Dialekten außerdem den Unterstrich. Diese dürfen in einem Hostnamen alle nicht auftreten. Wir sollten also ˹[a-zA-Z0-9]˼ oder, zusammen mit dem /i-Modifikator, ˹[a-z0-9]˼ verwenden. Hostnamen dürfen dagegen den Bindestrich enthalten, also nehmen wir ˹[-a-z0-9]˼ (und stellen wiederum sicher, dass der Bindestrich als erstes Element in der Zeichenklasse auftritt). So ergibt sich für den Hostnamen-Teil ˹[-a-z0-9]+(\.[-a-z0-9]+)*\.(com|edu|info)˼.

Wie bei allen Beispielen ist der Zusammenhang wichtig, in dem die Regex verwendet wird. Für sich genommen, würde ˹[-a-z0-9]+(\.[-a-z0-9]+)*\.(com|edu|info)˼ auch auf einen String wie ›Beim Booten C:\\startup.command ausführen‹ passen, aber durch den weiteren Zusammenhang des Programms ist sichergestellt, dass der Unterausdruck nur dort passen kann, wo wir es wollen. Wir können den Unterausdruck jetzt in das Schema

$text =~ s{\b(username-regex\@hostname-regex)\b}{<a href="mailto:$1">$1</a>}gi;

von vorhin einsetzen (wir haben außerdem andere Begrenzer s{...}{...} und den Modifikator /i genommen), aber das würde niemals auf eine Zeile passen. Perl schert sich keinen Deut um überlange oder schrecklich aussehende Zeilen, ich aber schon. Deshalb führe ich jetzt den /x-Modifikator ein, mit dem wir die Regex wie folgt darstellen können:

$text =~ s{
  \b 
  # Adresse in $1 abspeichern ... 
  ( 
    username-regex 
    \@ 
    hostname-regex 
  ) 
  \b 
}{<a href="mailto:$1">$1</a>}gix;

Sieht doch schon ganz anders aus! Der Modifikator /x ganz am Ende (hier kombiniert mit /g und /i) bewirkt zwei Dinge: Einmal wird Whitespace in der Regex nicht mehr beachtet, sodass man reguläre Ausdrücke in einem freieren Format schreiben kann, und außerdem kann man mit # Kommentare in der Regex unterbringen.

Bei der Verwendung von /x werden die meisten Whitespace-Zeichen zu »Ignorier’ mich!«-Metazeichen, und # wird zu einem Metazeichen für »Ignorier’ mich und alles bis zum Ende der Zeile!« (siehe den Abschnitt Der Modus »Freie Form«). Innerhalb von Zeichenklassen sind das nach wie vor keine Metazeichen (daraus folgt, dass man Zeichenklassen nicht im freien Format schreiben kann, auch nicht mit /x), und ganz analog zu anderen Metazeichen bekommt man das entsprechende Literal, wenn man einen Backslash davorstellt. Nach wie vor kann man ˹\s˼ als Metazeichen für Whitespace verwenden, zum Beispiel bei m/<a \s+ href=...>/x.

Das /x bezieht sich allerdings nur auf die Regex und nicht auf den Ersatztext. Obwohl wir hier statt Schrägstrichen die Form mit geschweiften Klammern (s{...}{...}) verwenden und die Modifikatoren hinter der zweiten geschlossenen Klammer angegeben werden (d. h. als ›}x‹), bezeichnen wir den »x-Modifikator« nach wie vor als »/x«.

Zusammengesetzt

Nun können wir die Unterausdrücke für Username und Hostname in das weiter vorne entwickelte Programm einsetzen und erhalten:

undef $/;                # »Ganze Datei«-Modus aktivieren.
$text = <>;              # Die gesamte auf der Befehlszeile angegebene Datei einlesen.

$text =~ s/&/&amp;/g;    # Die HTML-Zeichen ...
$text =~ s/</&lt;/g;     # ... &,  <  und  > ...
$text =~ s/>/&gt;/g;     # ... unschädlich machen.
$text =~ s/^\s*$/<p>/mg; # In Abschnitte aufteilen.

# E-Mail-Adressen in Links verwandeln ...
$text =~ s{
   \b
   # Adresse in $1 abspeichern ...
   (
     \w[-.\w]*                                  # Username
     \@
     [-a-z0-9]+(\.[-a-z0-9]+)*\.(com|edu|info)  # Hostname
   )
   \b
}{<a href="mailto:$1">$1</a>}gix;

print $text;                                    # Fertig; HTML ausgeben.

Alle regulären Ausdrücke werden auf den gleichen String angewandt, der aus mehreren logischen Zeilen besteht, aber nur bei der Regex, die den Text in Abschnitte unterteilt, mussten wir den /m-Modifikator angeben; nur diese Regex enthält nämlich ein ˹^˼ oder ein ˹$˼. In den anderen Fällen hätte das /m aber nicht geschadet (außer dass sich ein Leser gefragt hätte, warum da ein /m verwendet wurde).

HTTP-URLs »verlinken«

Als letzte Weiterentwicklung wollen wir auch normale HTTP-URLs als Hyperlinks darstellen. Eine URL der Art "http://www.yahoo.com/" soll in folgenden Link verwandelt werden: <ahref="http://www.yahoo.com/">http://www.yahoo.com/</a>.

Die Grundform einer HTTP-URL ist »http://Hostname/Pfad«, wobei der /Pfad-Teil fehlen kann. Wir beginnen mit diesem Schema:

$text =~ s{
   \b
   # URL in $1 abspeichern ...
   (
      http:// Hostname
      (
         / Pfad
      )?
   )
}{<a href="$1">$1</a>}gix;

Für den Hostname-Teil nehmen wir den gleichen Unterausdruck wie bei der E-Mail-Adresse. Der Pfad-Teil einer URL kann viele verschiedene Zeichen enthalten; unter Erweiterung der Fundamente hatten wir ˹[-a-z0-9_:@&?=+,.!/~*'%$]*˼ verwendet – das sind fast alle ASCII-Zeichen außer Whitespace, Kontrollzeichen und <, >, (, ), { und }.

In Perl müssen wir wiederum die Zeichen @ und $ mit einem Backslash schützen, und noch einmal verschieben wir diese Diskussion auf später. Wir setzen jetzt die Hostname- und Pfad-Teile ein:

$text =~ s{
   \b
   # URL in $1 abspeichern ...
   (
      http:// [-a-z0-9]+(\.[-a-z0-9]+)*\.(com|edu|info) \b # Hostname
      (
         / [-a-z0-9_:\@&?=+,.!/~*'%\$]*  # Optionaler Pfad-Teil
      )?
   )
}{<a href="$1">$1</a>}gix;

Beachten Sie, dass am Ende des Pfad-Teils kein ˹\b˼ steht, weil es durchaus Pfade gibt, die nicht mit einem alphanumerischen Zeichen enden, beispielsweise die URL bei O’Reilly zu diesem Buch, die "http://www.oreilly.de/catalog/regex3ger/" lautet. Ein ˹\b˼ am Ende würde solche URLs verbieten.

Dennoch ist es im Allgemeinen ungünstig, wenn man am Ende einer URL alle oben genannten Zeichen zulässt. Bei einem Text wie

Schräge Neuigkeiten gibt es bei "http://dailynews.yahoo.com/h/od", technische News bei "http://www.slashdot.com!"

würde unsere Regex den markierten Text erkennen, obwohl für einen menschlichen Leser klar ist, dass weder das Komma noch das Ausrufezeichen zur URL gehören. Wenn URLs in normalem Text vorkommen, ist es wahrscheinlich gescheiter, wenn man fordert, dass sie nicht mit ˹[.,?!]˼ enden sollten (das steht in keinem Standard, es stellt sich nur heraus, dass man damit die meisten Fälle bewältigt). Nun, dafür scheint ein negatives Lookbehind ˹(?<![.,?!])˼ am Ende des Pfad-Teils wie geschaffen. Am Ende der URL angekommen, muss die Regex-Maschine wegen des Lookbehinds »zurückschauen« und das zuletzt erkannte Zeichen noch einmal untersuchen. Wenn das Zeichen nicht passt, muss die Maschine ein Zeichen zurückgeben, damit das negative Lookbehind passen kann. (Wir werden unter Regex-Methoden aus der Praxis eine andere Lösungsmöglichkeit behandeln.

Wenn wir die Regex einsetzen, erhalten wir das fertige Programm:

undef $/;                   # »Ganze Datei«-Modus aktivieren.
$text = <>;                 # Die gesamte auf der Befehlszeile angegebene Datei einlesen.

$text =~ s/&/&amp;/g;       # Die HTML-Zeichen ...
$text =~ s/</&lt;/g;        # ... &,  <  und  > ...
$text =~ s/>/&gt;/g;        # ... unschädlich machen.

$text =~ s/^\s*$/<p>/mg;    # In Abschnitte aufteilen.

# E-Mail-Adressen in Links verwandeln ...
$text =~ s{
   \b
   # Adresse in $1 abspeichern ...
   (
     \w[-.\w]*                                              # Username.
     \@
     [-a-z0-9]+(\.[-a-z0-9]+)*\.(com|edu|info)              # Hostname.
   )
   \b
}{<a href="mailto:$1">$1</a>}gix;

# HTTP-URLs in Links verwandeln ...
$text =~ s{
   \b
   # URL in $1 abspeichern ...
   (
      http:// [-a-z0-9]+(\.[-a-z0-9]+)*\.(com|edu|info) \b  # Hostname.
      (
         / [-a-z0-9_:\@&?=+,.!/~*'%\$]*                     # Optionaler Pfad.
           (?<![.,?!])                                      # Darf nicht mit [.,?!] enden.
      )?
   )
}{<a href="$1">$1</a>}gix;

print $text;                                                # Fertig; HTML ausgeben.

Eine Regex-Sammlung

Sie werden bemerken, dass für die zwei Hostnamen der gleiche reguläre Ausdruck verwendet wird. Wenn der eine verändert wird, muss man daran denken, auch den anderen nachzuführen. Im folgenden Programmausschnitt kommt $HostnameRegex dreimal vor:

$HostnameRegex = qr/[-a-z0-9]+(\.[-a-z0-9]+)*\.(com|edu|info)/i;

# E-Mail-Adressen in Links verwandeln ...
$text =~ s{
   \b
   # Adresse in $1 abspeichern ...
   (
     \w[-.\w]*                             # Username.
     \@
     $HostnameRegex                        # Hostname.
   )
   \b
}{<a href="mailto:$1">$1</a>}gix;

# HTTP-URLs in Links verwandeln ...
$text =~ s{
   \b
   # URL in $1 abspeichern ...
   (
      http:// $HostnameRegex \b            # Hostname.
      (
         / [-a-z0-9_:\@&?=+,.!/~*'%\$]*    # Optionaler Pfad.

           (?<![.,?!])                     # Darf nicht mit [.,?!] enden.
      )?
   )
}{<a href="$1">$1</a>}gix;

In der ersten Zeile sehen wir den qr-Operator von Perl zum ersten Mal. Er ähnelt den m- und s-Operatoren insofern, als er eine Regex als Parameter erwartet (d.h. er wird wie qr/.../ benutzt, ganz analog zu m/.../ und s/.../.../). Die Regex wird hier aber nicht sofort auf einen Suchtext angewendet, um eine Mustersuche auszuführen, sondern sie wird in ein Regex-Objekt verwandelt, das man in einer Variablen abspeichern kann. Diese Variable kann später statt eines regulären Ausdrucks verwendet werden – oder auch als Unterausdruck in einer größeren Regex (wie hier; in diesem Beispiel haben wir das in $HostnameRegex abgespeicherte Regex-Objekt als Teil einer Regex in den zwei Substitutionen verwendet). Das ist sehr praktisch, weil es das Programm viel klarer macht. Außerdem muss jetzt die Regex nur noch an einem Ort verändert werden, wenn wir die Regex für den Hostnamen anpassen wollen. Weitere Beispiele für diese Art von Regex-Sammlung finden Sie unter Die Kunst, reguläre Ausdrücke zu schreiben, eine detaillierte Beschreibung unter Perl.

In anderen Sprachen gibt es andere Möglichkeiten, um Regex-Objekte zu erzeugen. Einige davon werden wir unter Features und Dialekte kurz streifen, Java und .NET unter Java und .NET.

Warum ›$‹ und ›@‹ manchmal maskiert werden müssen

Es ist Ihnen sicher aufgefallen, dass das Dollarzeichen einerseits das Metazeichen für das Zeilenende ist, andererseits dient es auch dazu, den Inhalt von Variablen in regulären Ausdrücken einzufügen, die Variablen also zu interpolieren. Normalerweise gibt es da keine Verwechslungsgefahr, aber innerhalb einer Zeichenklasse wird es etwas verzwickter. In einer Zeichenklasse macht ein Zeilenende keinen Sinn, deshalb versteht Perl das Dollarzeichen als Aufforderung, eine Variable zu interpolieren – außer natürlich, wenn das Dollarzeichen mit einem Backslash maskiert ist (\$). Deshalb mussten wir das Dollarzeichen im Unterausdruck für die HTTP-URL maskieren.

Ganz ähnlich ist es mit @. In Perl bezeichnet @ den Anfang eines Array-Namens, und in regulären Ausdrücken bzw. in Strings in Anführungszeichen werden Arrays normalerweise interpoliert, das heißt, die Array-Werte werden eingefügt. Wenn wir in einer Regex ein literales @ haben wollen, müssen wir es maskieren, damit Perl nicht versucht, eine Array-Interpolation vorzunehmen. In manchen Sprachen können Arrays nicht interpoliert werden (in Java, VB.NET, C, C#, Emacs, awk und anderen), in anderen geht das (in Perl, PHP, Python, Ruby und Tcl) – aber bei jeder Sprache geschieht das auf andere Weise. Das wird unter Features und Dialekte genauer beleuchtet.

  

<< 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