Reguläre Ausdrücke - eine Sammlung

Allgemeines

Hier findest du eine Sammlung von ausgearbeiteten Regulären Ausdrücken für alltägliche Belange wie z.B. MAC-Adressen oder Datumse. Reguläre Ausdrücke sind ein mächtiges Werkzeug um Muster in Zeichenketten zu erkennen und zu verarbeiten. Irgendwann war ich mal auf der Suche nach diesem und jenem Ausdruck, konnte jedoch nichts im Netz finden. Das war die Geburtsstunde dieser Sammlung regulärer Ausdrücke. Da ist sie!

Einführung

Reguläre Ausdrücke sind ein mächtiges Werkzeug, das jeder beherrschen sollte. In Programmen kann man oft mehrere 10 Zeilen lange Algorithmen durch eine einzige Zeile ersetzen - und das noch zumeist umfassender. Reguläre Ausdrücke sind einfach supertoll. Passende RegEx-Maschinen für diverse Programmiersprachen sind findet man auf dieser Seite. Vor allem eignen sich aber die Hig-Level-Skriptspachen à la Ruby, Perl, Python oder tcl, da sie eingebaute Unterstützung haben. Also immer in Betracht ziehen.

Für die Beispiele hier wurden Perl- bzw. Ruby-Kompatible reguläre Ausdrücke verwendet. Es gibt nämlich nicht die Sprache der regulären Ausdrücke, sondern viele Geschmäcker. Die unterscheiden sich in Syntax und Merkmalen. Als einziges besonderes Merkmal werden hier die nicht einfangenden Klammern ((?:  )) benutzt.

Man beachte auch, dass die Ausdrücke hier zumeist mit ^ beginnen und mit $ enden. Die Verwendung dieser Anker ist guter Stil und macht die regulären Ausdrücke robuster und eindeutiger. Für den Fall, dass man ein Muster, welches in Freiräumen eingebettet ist, erkennen möchte, muss man den Ausdruck nach ^ und vor $ zusätzlich mit \s* versehen. Ähnliches gilt auch, wen man sie einbetten möchte. Dann müssen ^ und $ raus.

Beispiele

Extrahiert name, typ und ues aus Schema-Attribut-Elementen:

Diesen regulären Ausdruck habe ich seinerzeit einmal benötigt um aus dem Kennzeichen <attribute /> aus XML-Schema einzelne Attribut-Werte zu extrahieren.

/^.*attr.*name=\"\([^\"]*\)\".*type=\"\([^"]*\)\".*use=\"\([^"]*\)\".*/

Simple E-Mail-Adresse:

Dies hier ist eine starke vereinfachung aber eine doch in 99% ausreichende Lösung für das Problem "E-Mail-Adresse". Eine Adresse nach RFC-822 darf nämlich neben einer Beschreibung beliebig Kommentare (runde Klammern) und diese beliebig geschachtelt enthalten. Nur benutzt es praktisch Keiner, wesshalb auch dieser reguläre Ausdruck genügt. Er erkennt z.B. ham@no-spam.nu.com . Also mindestens ein Zeichen vor @ und mindestens zwei durch einen Punkt getrennte Worte dannach:

/^.+@.+\.[^.]{2,}$/

E-Mail-Adresse (RFC-angenähert) -> Kommentarfeld und Beschreibung

Eine E-Mail-Adresse nach RFC-822 ist weit komplexer als man eine solche Adresse gemeinhin kennt. Sie darf neben einer Beschreibung auch ein Klammergebirge (den Kommentar) enthalten und noch Einiges mehr. Klammergebirge sind bekanntlich nicht mit regulären Sprachen darstellbar. Daher kann man sich auf einen Kompromiss einigen, der z.B. maximal 6 Kommentarebenen erlaubt. Unser aller reguläre Asudrücke-Spezialist Jeffrey E.F. Friedl hat sich diesem Problem automatisiert gehähert und dabei einen 6598 Zeichen langen regulären Ausdruck erhalten.

----Bislang habe ich ihn jedoch nicht eingefügt---------

IPv4-Adresse (dezimal):

Eine dezimale IPv4-Adresse ist die heute übliche und meist schlicht IP-Adresse benannte Zeichenkette. Beispielsweise 123.10.0.182

/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/

IPv4-Adresse (hex):

Eher weniger bekannt, weil auch nicht sehr gebräuchlich ist die IP-Adresse in Hex-Darstellung: 0xD4.0xCC.0x65.0xD2 der folgende Ausdruck erkennt dieses Muster und bringt auch gleich einfangende Klammern mit, die die Hex-Zahlen extrahieren:

/^0x([\da-fA-F]{2})\.0x([\da-fA-F]{2})\.0x([\da-fA-F]{2})\.0x([\da-fA-F]{2})$/

IPv6-Adresse:

Für die IPv6-Adresse gibt es eine ganze Menge von Kodierungen. Die bekannteste soll hier vorgestellt werden. Die sedezimale blockweise Darstellung. Auf exotisches wie z. B. eine base64-kodierte Variante verzichten wir hier.

Vollständige Adrese mit allen Abschnitten sedezimale Notation, fix 4 Ziffern je Block: 4030:00BC:0000:00A4:0267:01FF:FE01:7352

/^([0-9A-Fa-f]{4}:){7}[0-9A-Fa-f]{4}$/

Ohne verpflichtende führende Nullen je Block, sedezimale Notation: 4030:B:0:A4:267:1F:0:52

/^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$/

Die Auslassung mehrerer Nullblöcke und deren Reduzierung auf ein :: ist mit regulären Ausdrücken nur mit hohem Schreibaufwand korrekt lösbar. Reguläre Ausdrücke können nunmal nicht zählen. Man kann sich allerdings mit halben Lösung behelfen und im Zweifel mehr Blöcke zulassen. ::4030:A4:0:2:7352 ; :: ; 2030:34E3::8CF3:7623 Also vorne bis zu sieben und hinten bis zu sieben. Naja:

/^(([0-9A-Fa-f]{1,4}:){1,7}|:)(:|([0-9A-Fa-f]{1,4}:){1,7})$/

Heißt so viel wie 1-7 Blöcke mit Doppelpunkt hinten ODER bei 0 Blöcken nur einen Doppelpunkt. Und dann das Ganze nochmal rückwärts.

Weitere Infs gibt es unter http://www.rdfnuernberg.de/iav1a/theorie/adresskonzepte.html

MAC-Adresse:

MAC-Adressen sind die Hardwareadressen diverser Netzwerkprodukte. Es handelt sich dabei um eine 48-Bit Zahl, die weltweit eindeutig ist. Angegeben wird eine MAC-Adresse in Form von 6 Hex-Zahlen getrennt durch Doppelpunkte, Bindestriche, Leerzeichen oder nix.  Z.B. CB:35:2F:00:7C:A1

/^[\dA-Fa-f]{2}([-: ]?[\dA-Fa-f]{2}){5}$/

Hier ein Ausdruck um die einzelnen Komponenten zu extrahieren. Auch hier wieder getrennt durch Doppelpunkte, Bindestriche, Leerzeichen oder nix:

s/^([\dA-Fa-f]{2})[-: ]?([\dA-Fa-f]{2})[-: ]?([\dA-Fa-f]{2})[-: ]?([\dA-Fa-f]{2})[-: ]?([\dA-Fa-f]{2})[-: ]?([\dA-Fa-f]{2})$/\1:\2:\3:\4:\5:\6/

Ansprechbar sind die 6 Klammern (hier) über \x, die die 6 Komponenten repräsentieren

Datum und Uhrzeit

Hier folgen nun einige Reguläre Ausdrücke für Datum und Uhrzeit. Hier ist Vorsicht geboten in der Anwendung. Sie funktionieren zwar gut zur Validierung, doch sollte man sich bewust sein, dass dieses alles Lokalen-spezifische Ausdrücke sind. Datum und Uhrzeit gibt es in den verschiedendsten Geschmacksrichtungen und alle Reihenfolgen für Tag Monat Jahr existieren. Es ist ohne Kenntnis der Kultur (Lokale) in der das Programm läuft nicht möglich gezielt ein Datum zu parsen. Daher sollte man auf Funktionen zurückgreifen, die die aktuelle Kultur/Lokale des Benutzers berücksichtigen. Diese Ausdrücke hier sind fast nur für europäische Verhältnisse ausgelegt.

Datum dt. Unixisch (ca. 1970-2038 nicht genau):

Ein deutsches Datum besteht aus einem 1-2-stelligen Tag, einem 1-2-stelligen Monat und einem Jahr (2/4-stellig). Gespeichert wird ein Datum ganz gerne als 32-Bit-Zahl, die die Sekunden seit 1.1.1970 angibt. Dies kennt man gemeinhin von Unix so (1970 gilt als Start der Unix-Zeit). Mit einer 32-Bit-Zahl ist man jedoch auch beschränkt auf Datums bis 2038, was dieser Ausdruck zum Ausdruck bringt:

/^(31|30|[012]\d|\d)\.(0\d|1[012]|\d)\.(19[789]\d|20[0123]\d)$/

Datum dt. offene Jahreszahl

Ein deutsches Datum besteht aus einem 1-2-stelligen Tag, einem 1-2-stelligen Monat und einem Jahr (2/4-stellig). Dieser reguläre Ausdruck beschränkt zwar die Tage und Monate korrekt, erlaubt aber Jahreszahlen von 0-999999. Hier wird keine Rücksicht auf eventuelle Restriktionen seitens der Speicherung des Datums genommen. Daher immer schauen wofür das Datum gedacht ist. Beispiel: 1.03.8573

/^(31|30|[012]\d|\d)\.(0\d|1[012]|\d)\.(\d{1,6})$/

Datum offene 2,4-Stellige Jahreszahl und . sowie / als Trennzeichen

Dieser Ausdruck passt auf englische oder europäische Daten mit 2- oder 4-stelliger Jahreszahl. Dabei passen die Jahre 00-9999. Für die erste Zahl sind 1-31 möglich und für die zweite Zahl sind nur 1-12 möglich. Mithin sind daher möglich: 31.02.2033; 22.4/99; 1/1/8483

^/(31|30|[012]\d|\d)[./](0\d|1[012]|\d)[./](\d{4}|\d\d)$/

Uhrzeit 12h (kein AM/PM):

eine Uhrzeit wie 09:44

/^(0\d|1[012]|\d):([0-5]?\d)$/

Uhrzeit 24h:

Eine Uhrzeit, wie sie gemeinhin im Europäischen Raum verwendet wird: 22:46

/^([01]?\d|2[0-3]):([0-5]?\d)$/

Uhrzeit 12/24h ohne Sekunden mit optionalem AM/PM:

Erkannt wird eine Uhrzeit ohne Sekunden, wie sie gemeinhin im Europäischen Raum verwendet wird. Entweder als 24 Stunden-Schreibweise oder als 12 Stunden schreibweise aber dann mit AM/PM in Groß- Klein- oder Gemischtschreibung: 22:46; 12:46; 1:06 aM; 05:44 PM nicht 22:33 Pm oder 3:87

/^(([01]?\d|2[0-3]):([0-5]?\d))|((0\d|1[012]|\d):([0-5]?\d) [aApP][mM])$/

Uhrzeit 12/24h mit optionalen Sekunden mit optionalem AM/PM:

Erkannt wird eine Uhrzeit mit/ohne Sekunden, wie sie gemeinhin im Europäischen Raum verwendet wird. Entweder als 24 Stunden-Schreibweise oder als 12 Stunden schreibweise aber dann mit AM/PM in Groß- Klein- oder Gemischtschreibung: 22:46:33; 22:46; 12:46; 1:06 aM; 3:06:32 Pm; 05:44 PM nicht 22:33 Pm oder 3:87

/^(([01]?\d|2[0-3]):([0-5]?\d)(:([0-5]?\d)?))|((0\d|1[012]|\d):([0-5]?\d)(:([0-5]?\d))? [aApP][mM])$/

Uhrzeit 24h mit Sekunden:

Eine Uhrzeit mit Sekunden, wie sie gemeinhin im Europäischen Raum verwendet wird: 22:46:33

/^([01]?\d|2[0-3]):([0-5]?\d):([0-5]?\d)$/

Datum mit Punkt oder Schrägstrich und 12/24h Zeit mit optionalen Sekunden und mit optionalem AM/PM:

Ein Datum im europäischen oder englischen Stil mit Tag Monat Jahr und diese jeweils durch / oder . getrennt. (optional) Daran angehängt eine Uhrzeit wie eins zuvor besprochen. 12/24h mit optionalen Sekunden und optionales AM/PM in groß oder klein. Dabei geht AM/PM nur bei 12h Schreibung. Zwischen beidem Steht mindestens 0 Whitespace. Nicht ganz perfekt aber gut genug. Beispiele umfassen: 22:46; 12:5 Pm; 1/7/12 22:46; 22.03.2006 1:16 aM; 31/2.06 22:33:22; 22.46.03; 1.3/1999

^((31|30|[012]\d|\d)[./](0\d|1[012]|\d)[./](\d{1,6}))?\w*(([01]?\d|2[0-3]):([0-5]?\d)(:([0-5]?\d)?))|((0\d|1[012]|\d):([0-5]?\d)(:([0-5]?\d))? [aApP][mM]))?$

Zeichenkette in Anführungszeichen:

Oft möchte man eine Zeichenkette in Anführungszeichen erkennen. Ein dabei oft begangener Fehler ist es, für die Zeichenkette .* zu spezifizieren. Da der Punkt auch auf Das Anführungszeichen passt wird wegen der gierigen Quantoren (*) z.B. diese Zeichenkette falsch erkannt:
Trallala "hier beginnts und da is aus" das geht darüber hinaus" ba.
Ein solcher regulärer Ausdruck würde vom ersten bis einschlielich dritten Anführungszeichen erkennen. Dieser Ausdruck erkennt nur vom ersten bis zum zweiten Anführungszeichen, wie es gedacht war:

/"[^"]*"/

Zeichenkette in einfachen Anführungszeichen

Dieser Ausdruck erkennt dasselbe wie der vorangegangene. Jedoch statt der doppelten die einfachen Anführungszeichen ('):

/'[^']*'/

Fließkommazahl (auch als Ganzzahl) mit Vorzeichen und Exponent

Beispiele die hier erkannt werden sind: 4 ; 00049 ; +45,34 ; -533 ; -,3 ; +4,3e-23 ; 33E+2

/^[+-]?(\d*,\d+|\d+(,\d*)?)( +[eE][+-]?\d+)?$/

Fließpunktzahl:

Dies ist dasselbe wie eins drüber, nur statt Komma jetzt Punkt.

/^[+-]?(\d*\.\d+|\d+(\.\d*)?)( +[eE][+-]?\d+)?$/

ISBN mit und ohne Literal "ISBN" davor:

Hier ein Ausdruck zum Erkennen von ISB-Nummern der Art ISBN 3-925660-91-7 oder nur 3-925660-91-7. Auf die korrekte Berechnung der Kontrollziffer konnte keine Rücksicht genommen werden, da die regulären Ausdrücke das nicht hergeben.

/^(ISBN )?\d-\d{6}-\d\d-\d$/

HTTP(S)- bzw. FTP-URL

Dieser Ausdruck findet heraus, ob eine übergebene Zeichenkette einen URL repräsentiert. Dabei sind die Protokolle http, https und ftp zugelassen. Gorß-/Kleinschreibung ist dabei egal. Es werden Protokoll und der Teil hinter "://" eingefangen. Der Ausdruck ist recht großzügig bemessen. Von Fall zu Fall sollte man ihn also noch insofern verfeinern, dass er nebst einem Host auch mindestens einen Pfad haben oder auf "/" enden muss. Ebenfalls unbeachtet ist die Tatsache, dass HTTP und FTP auch einen Benutzer+Kennwort haben können (https://ich:geheim@sonstwo.no/meinVZ/).

/^([Hh][Tt][Tt][Pp][Ss]?|[Ff][Tt][Pp]):\/\/(.+)$/

Stand: Anfang 2004 Robert Köpferl

Wer weitere reguläre Ausdrücke für mich hat, darf sie mir gerne zusenden, ich baue sie gerne ein: RFC822[regex.au )auf( koepferl.de]