Fork me on GitHub

Web Development

Ein Lehrbuch für das Informatik oder Medien-Informatik Studium.

Regular Expressions sind eine kleine “Programmiersprache in der Programmiersprache”, eine besondere Schreibweise die es erlaubt in Strings nach Mustern zu suchen und Ersetzungen vorzunehmen.

Mit Regular Expressions kann man die Welt retten:

Basierend auf http://xkcd.com/208/ von Randall Munroe - verändert und verwendet unter der CC-BY-NC Lizenz

Regular Expressions sind keine Besonderheit von Javascript. Viele UNIX Kommandozeilen-Befehle und die meisten Programmiersprachen bieten Regular Expressions an. Egal ob Sie also mit vi, grep, mod_rewrite, Javascript, C++ oder Ruby arbeiten, alles was Sie über Regular Expressions lernen zahlt sich aus!

Reguläre Ausdrücke sind ein Konzept aus der Theoretischen Informatik. Diese ursprünglichen regulären Ausdrücke bieten nur 3 Operatoren an. Bei der Umsetzung in diversen UNIX-Tools und Programmiersprachen wurden mehr und mehr Operatoren eingeführt. Zur unterscheidung nenne ich diese erweiterten Ausdrücke mit dem englischen Begriff Regular Expressions oder kurz RegEx.

Regular Expressions nennt man oft auch Muster (en: patterns), man spricht von Mustersuche (en: pattern matching). Wenn ein Muster auf ein Zeichenkette zutrifft sagt man auf Halb-Englisch: “der Pattern matched”.

Verwendung von Regular Expressions

In Javascript gibt es viele verschiedene Schreibweise für Regular Expressions, wir beginnen mit der Methode match des String-Objekts:

Javascript Code match

var s = "begreifen";
if( s.match(/greif/) ) {
  console.log("greif gefunden!");
}

Hier wird im String “begreifen” nach dem String “greif” gesucht. Falls er gefunden wird (ja, wird er), gibt die Match-Methoden einen Wert zurück, der als wahr gilt.

Für diesen einfachen Fall wird man aber nicht eine RegEx verwenden, sondern indexOf: diese Methode gibt -1 zurück falls der String nicht gefunden wurde, und die Position der Fundstelle anderfalls.

Javascript Code match

var s = "begreifen";
if( s.indexOf('greif') > -1) {
  console.log("greif gefunden!");
}

Zeichenkette

Die einfachste Regular Expression besteht aus einer Zeichenkette, nach der “wörtlich” gesucht werden soll. Falls die Zeichenkette irgendwo im String gefunden wird ist die Suche erfolgreich:

/hallo/

RegEx Tester: /hallo/

Alternative

Mit dem senkrechten Strich | kann man Alternative definieren, er entspricht also einem logischen “oder”;

/en|sk|zh|us|uk/

RegEx Tester: /en|sk|zh|us|uk/

Gruppieren und Merken

Mit runden Klammern kann man Teile der Regular Expression zusammen fassen:

/(de|fr)_(DE|CH)/

RegEx Tester: /(de|fr)_(DE|CH)/

Ausserdem stehen die von den Klammern gefundenen Teile des Strings nach der Auswertung zur Verfügung: die Methode match liefert ein Array als Rückgabewert, an der Stelle 0 ist der gesamte gefundene String gespeichert, auf 1, 2, 3 der Reihe nach die gefundnen Gruppen:

locale = "de_CH";
if( match = locale.match(/(de|fr)_(DE|CH)/ ) {
  console.log("gesamt:  " + match[0]);
  console.log("sprache: " + match[1]);
  console.log("land:    " + match[2]);
}

Verankern

Mit den Zeichen Zirkumflex ^ und Dollar $ kann die Suche am Anfang bzw. Ende der Strings verankert werden.

/^Am Anfang war/
/dann leben sie noch heute.$/
/^Ganzer String$/

RegEx Tester: /^(en|sk|us|uk)$/

Zeichen-Klassen

Wenn für ein Zeichen im String mehrere Zeichen zur Auswahl stehen fasst man sie in einer “Zeichen-Klasse” (en: “character class”) zusammen:

/[aeiou]/

Achtung! Eine Erwähnung der Zeichenklasse matched genau ein Zeichen im String, nicht mehrere Zeichen!

RegEx Tester: /hall[oia]/

Zeichen-Klasse mit Zeichenbereich

Mit einem Bindestrich - innerhalb der Klasse kann man einen Bereich von Zeichen angeben, die im Zeichensatz hintereinander stehen.

/[a-f]/

RegEx Tester: /[a-z]/

Komplement der Zeichen-Klasse

Mit dem Zirkumflex ^ kann man das Komplement der Zeichen-Klasse bilden, es werden dann alle Zeichen gematched die nicht in der eckigen Klammer erwähnt werden:

/[^aeiou]/

RegEx Tester: /u[^1234]/

Abkürzungen für häufig benutze Zeichenklassen

/\d/       eine Ziffer, entspricht /[0-9]/
/\D/       keine Ziffer, entspricht /[^0-9]/
/\w/       Wort-Zeichen, entspricht /[a-zA-Z0-9_]/
/\W/       kein Wort-Zeichen, entspricht /[^a-zA-Z0-9_]/

RegEx Tester: /u\d/

Irgend ein Zeichen

Der Punkt . steht für ein beliebiges Zeichen. Achtung, Verwechslungsgefahr: bei Pfadangaben hat das Fragezeichen ? diese Funktion!

/^...$/       genau drei Zeichen

RegEx Tester: /^…$/

Ein echter Punkt

Da der Punkt . eine besondere Bedeutung in einer Regular Expression hat stellt sich die Frage: wie erkennt man dann einen echten Punkt? Die Antwort: man escaped die Sonderzeichen von RegEx mit einem Backslash \.

/\./     ein echter punkt

RegEx Tester: /^\d.\d$/

Stern-Operator: beliebig viele

Der Stern-Operator dient der Vervielfältigung: das davor stehende Zeichen kann beliebig oft Wiederholt werden, also null-mal, ein-mal oder mehr-mals vorkommen:

/i*/  

Der Operator kann auch auf Zeichenklassen oder Gruppen angewandt werden. Wenn man sich den Operator als Schleif vorstellt kann bei jeder “Wiederholung” ein anderes Zeichen aus der Klasse oder eine andere Alternative gewählt werden:

/(do|re|mi)*/
/\d*/

RegEx Tester: /^\d*$/

Plus-Operator: mindestens einmal, oder mehrmals

Der Plus-Operator ähnelt dem Stern-Operator, allerdings muss das Zeichen mindestens einmal vorkommen.

/\d+/  

RegEx Tester: /^\d+$/

Fragezeichen-Operator: einmal oder keinmal

Der Frage-Operator erlaubt 0 oder 1 vorkommen des Zeichens.

/\d?/  

RegEx Tester: /^\d?$/

Operatoren sind gierig

Die Operatoren * und + versuchen immer möglichst lange Strings zu erfassen.

/o.*o/    möglichst viele Zeichen zwischen o und o

Diese Eigenschaft sieht man sehr gut in folgendem Beispiel:

RegEx Tester: /.*/

Wie kann man das gierige Verhalten der Operatoren umgehen?

Die “altmodisch” Methode ist eine Komplement-Klasse:

/o[^o]*o/    

Hier wird ein erstes o gematched, dann kommen (null bis viele) zeichen die kein o sind, und dann ein zweites o. Damit ist der Pattern beendet, auch wenn es später im String noch weitere o’s geben würde.

RegEx Tester: /[^]*_/

In modernen RegEx Engines gibt es nicht-gierige Varianten der Operatoren: ein Fragezeichen wird nachgestellt

/o(.*?)o/    
/o(.+?)o/    

RegEx Tester: /.*?/

Warnhinweis: Was RegEx nicht kann

Mit dem letzten Beispiel könnte man nun in Versuchung kommen verschachtelte Ausdrücke wie HTML, XML, mathematische Ausdrücke, Programmiersprachen mit Hilfe von RegEx zu parsen.

Das funktioniert aber nicht. Das müssten Sie an dieser Stelle einfach mal glauben - den Beweis überlassen wir der “Theoretischen Informatik”.

Wenn Sie also in Javascript oder PHP HTML oder XML parsen wollen, dann verwenden Sie dafür einen der vielen fertigen Parser.

Wenn Sie aus einem längeren HTML-Dokument “unverschachtelte” Teile wie z.B. <img> Tags herausholen wollen, dann könnsn Sie das mit Regular Expressions machen. Aber nichts komplizierteres.

Ersetzen mit Regular Expression in Javascript

Ein häufiger Anwendungsfall von RegEx ist “Suchen und Ersetzen”

s = "Voldemort hat keine Nase";
s.replace(/Voldemort/, 
          "Er, dessen Name nicht genannt werden darf,");

Es erfolgt nur eine einzige Ersetzung. Mit dem Modifikator g am Ende der RegEx kann man alle Ersetzungen durchführen:

s = "Voldemort hat keine Nase. Voldemort ist verschwunden.";
s.replace(/Voldemort/g, 
          "Er, dessen Name nicht genannt werden darf,");

Achtung, auch hier kommt man bald an die Grenzen von Regular Expressions:

s = "Harry greift Voldemort an. Voldemorts Zauberstab bricht.";
s.replace(/Voldemort/g, 
          "Er, dessen Name nicht genannt werden darf,");

Dass im zweiten Satz ein anderer Fall notwendig wäre, und wie man das dann richtige formuliert, kann eine Regular Expression nicht erkennen. Dafür gibt es eine eigene Wissenschaft: die Computer-Linguistik beschäftigt sich mit der Analyse, Synthese und Übersetzung von natürlichen Sprachen.

RegEx in PHP

Php Code RegEx Beispiel-Code aus Wordpress Plugins

# Beispiel Link Suchen
if (preg_match('/^(http)(s?)(:)\/\//',$linky)){ ...

# Beispiel Sprache-Code
if (preg_match ( "/en|sk|zh|us|uk/", $locale_code )){ ...

Php Code Suchen mit RegEx in PHP

preg_match( "/regex/i", "string in dem ich suche") 

Vertiefung

Merchandize