orm@doc-tcpip.org

Erstellt: Mai 1999 - Letzte Modifikation: Februar 2005

[ Main | Local ]


Einige Beispiele für Unix Regular Expressions

Weil man es immer vergisst.

Was sind Reguläre Ausdrücke?

Reguläre Ausdrücke sind ein mathematisches Konzept, mit dem man unter Benutzung von definierten Platzhaltern logische Zusammenhänge ausdrücken kann. In der Informatik nutzt man Reguläre Ausdrücke, um Muster zu erkennen und zu filtern.

Einteilung der Regulären Ausdrücke

Es gibt Literale, Metacharaktere, Charakterklassen und Metasequenzen.

Je nach benutztem Werkzeug (grep, egrep, Perl ...) unterscheiden sich die Implementationen der Regulären Ausdrücke gewaltig, sowohl im Umfang wie auch in der Funktion. Es gibt keinen Standardsatz an Regulären Ausdrücken; nur bei einfachen Ausdrücken kann man von einer gewissen Portabilität ausgehen - so sind die gängigen Metacharaktere mittlerweile quasi-Standard. Bei gepflegten Werkzeugen werden zusätzlich die Funktionalitäten regelmäßig erweitert, da alle Programmierer immer fleißig abgucken.

Wie wird ein Regulärer Ausdruck ausgewertet?

Es ist wichtig, sich klarzumachen, daß ein Regulärer Ausdruck nicht in seiner Gesamtheit bewertet und erkannt wird. Der Vergleich erfolgt Position für Position, und beim ersten Unterschied wird abgebrochen. So wird der Reguläre Ausdruck ^orm so Verglichen: "Der Anfang einer Zeile, gefolgt von einem kleinen o, gefolgt von einem kleinen r, gefolgt von einem kleinem m".

Das grep-Kommando

egrep, grep, fgrep -i: case insensitiv

Metacharaktere, Metazeichen

Ein Metazeichen bezieht sich immer auf ein vorangehendes Zeichen; ein Ausnahme bilden die Metazeichen, die eine Position darstellen (Positionsanker). Das links stehende (vorangehende) Zeichen kann auch eine Gruppe oder Klasse sein. Jedenfalls immer eine und nur eine Position.

Charakterklassen

Ckarakterklassen sollte man als Regulären Ausdruck in einem Regulären Ausdruck betrachten. Man kann in einer Charakterklasse Literale und Funktionen zusammenfassen. Eine bestimmte Position wird dann gegen eine definierte Gruppe von Zeichen verglichen.

So findet [ab] entweder "a" oder "b", also immer nur ein Zeichen pro Klammerausdruck. In diesem Fall hätte man auch eine Auswahl angeben können: (a|b). Mit folgenden Charakterklassen wird das ganze klarer: H[123456] (bzw. H[1-6]) findet H1, H2 etc.

So ist zB. [A-Fa-f0-9] praktisch, wenn man mit hexadezimalen Zahlen arbeitet.

Probleme gibt es dann, wenn in einer Charakterklasse Metazeichen auftauchen - schließlich kann es ja sein, daß man die Funktion des Metazeichen haben möchte oder aber die wörtliche Bedeutung. In einer Charakterklasse sind Metacharaktere in der Regel Literale. Die eckigen Klammern heben die spezielle Bedeutung der Metcharaktere auf. Eine Ausnahme ist der Bindestrich. Er zeigt einen Bereich an und ist nur an erster Stelle als Literal anzusehen: [0-9_!.?] findet eine Zahl oder die Sonderzeichen _, !, ., ?. Möchte man auch den Bindestrich finden, so muß dieser an der ersten Stelle stehen - nur dort wird er wörtlich genommen: [-0-9_!.?].

Den Inhalt einer Charakterklasse kann man negieren: [^1-6] findet jedes Zeichen, daß nicht 1, 2, 3, 4, 5, oder 6 ist. Das Caret ist also ein weiterer Metacharakter, der seine speziellen Eigenschaften in einer Charakterklasse behält - allerdings wieder nur an erster Stelle; sonst wird es als Literal gewertet.

z[^w] findet alle Stellen, wo "z" nicht von einem "w" gefolgt wird. Es muß aber ein Zeichen folgen.

Der Punkt ist die Charakterklasse "ein beliebiges Zeichen". Taucht der Punkt in einer Charakterklasse auf, so ist er ein Literal. Nochmal zur Stellung in einer Charakterklasse:

Wie findet man ein Datum? Es gibt schließlich eine Reihe Formate wie 05.03.2002, 05/03/2002 oder 05-02-2002. Man kann das Problem mit Punkten angehen: 05.03.2002. Der Punkt als Charakterklasse "beliebiges Zeichen" findet alle Zeichen, auch Zahlen etc. an den entsprechenden Stellen.

Daher bildet man präziser die Charakterklasse [-./].

Wie findet man einen 24-Stunden Zeitstempel (07:34:44)? Dazu ein paar Möglichkeiten:0?[0-9]|1[0-9]|2[0-3] oder [01]?[0-9]|2[0-3] oder [01]?[4-9]|[012]?[0-3].

Will man einzelne Buchstaben finden, so kann man eine Charakterklasse, eine Oder-Verknüpfung oder eine Alternative in einer Klammer angeben. Das Ergebnis ist gleich, aber auf ganz unterschiedliche Weise zustande gekommen: Die Charakterklasse "iy": me[iy]er, "meier" oder "meyer": meier|meyer und die Alternative: me(i|y)er. Das ist auch nützlich beim Auswerten von Mailfiles: ^(From|Subject|Date):.

Metasequenzen

Sind Kombinationen von Metazeichen, die eine neue Funktion bezeichnen. Im Prinzip also nur eine nötige Erweiterung der Metazeichen, einfach wiel nicht genügend Zeichen zur Verfügung stehen. Auch hier gilt wieder, das nicht alle Werkzeuge alle geschilderten Metasequenzen auch tatsächlich implemetieren.

\< bzw. \> bezeichnet Wortenden. Der Reguläre Ausdruck \ findet also "Orm", und auch nur als eigenes Wort. orm\> findet "Form" etc. (alle Wörter mit "orm" am Ende.

Backreferenzen

Viele Implementationen stellen sogenannte Backreferences zur Verfügung. Dabei kann in einem Ausdruck Bezug genommen werden auf ein vorher erkanntes Muster.

Ein Beispiel: \<([A-Za-z]+) +\1\>
Dieser Ausdruck findet alle doppelten Worte. Der Ausdruck in den runden Klammern ist ein beliebiges Wort; er wird in der Variable $1 gespeichert - das gilt generell für alle Ergebnisse der Ausdrücke in runden Klammern. Mit der Metasequenz \1 wird sich auf diese Variable bezogen. Das Wort muß also nochmal vorkommen. Das Plus erlaubt beliebige (mindestens ein) Leerzeichen. Sind mehrere Klammerterme vorhanden, so wird hochgezählt: (xxx) (yyy) (zzz) \1 \2 \3.

Weitere Standard Probleme