Reguläre Ausdrücke (regular expressions, regexp)


Reguläre Ausdrücke sind Zeichenketten (einzeilige Texte), die dem Prinzip folgen, das sie aus einer Folge von Bezeichnungen, was auftreten darf (Zeichen oder Zeichenklasse) und wie oft (sogenannte „Quantifiers“), bestehen. Standard (Default) für den Quantifier ist dabei die 1. Außerdem steht natürlich erst mal jedes Zeichen für sich selbst. Das bedeutet, dass man zunächst einmal, ganz normales Finden oder Suchen/Tauschen machen kann. „Abc“ findet „Abcdef“ (Achtung! Reguläre Ausdrücke sind GROSS-kleinschreibung-sensitiv, also „Abc“ und „abc“ sind unterschiedlich!), und Ersetzen von „Abc“ durch „XX“ liefert im vorgenannten Beispiel „XXdef“.

Quantifier

Die wichtigsten Quantifier sind „?“, „*“ und „+“. Die Bedeutung dabei:

?

einmal oder kein mal

*

beliebig oft (einschließlich kein mal)

+

beliebig oft, aber mindestens einmal

Beispiele:

Suche nach „a?bc“ in „bc“ liefert Treffer, denn das „a“ kann, muss aber nicht auftauchen. „a*bc“ trifft auf „bc“, aber auch auf „abc“ und „aaabc“ zu. „a+bc“ trifft NICHT auf „bc“, aber auf „abc“ und „aaabc“ zu.


Allgemeiner und genauer geht’s mit der Angabe {min, MAX}. „?“ entspricht beispielsweise der Angabe {0, 1}, „*“ ist {0,} und „+“ ist {1,}. {,3} würde bedeuten „höchstens drei mal“ und {3,} wäre „mindestens drei mal“. Und {5} trifft nur bei „genau fünf mal“.


Beispiel:

„a{1,3}bc“ trifft NICHT auf „bc“, aber auf „abc“ und „aaabc“ zu. „a{5}bc“trifft NICHT, außer wenn „aaaaabc“ im Text enthalten ist. Suchen/Tauschen mit „a{5}bc“ und „YY“ auf „XaaaaabcX“ liefert „XYYX“.

Greedy versus Non-Greedy (Reluctant) Matching

Normalerweise ist das Suchen Greedy („gierig“), das heißt, es wird der längste String (die längste Zeichenkette) genommen, auf die das Suchmuster passt. Mit einem hinzugesetzten „?“ kann man auf „reluctant“ („zurückhaltend“, “widerwillig“, „zögernd“) Matching umschalten, d.h. der String wird jetzt so kurz wie möglich gewählt, so dass es gerade eben noch passt.


Beispiel:

„a+?bc“ ersetzt durch „XX“ liefert auf „YaaabcY“ „YaaXXY“ und nicht „YXXY“.

Zeichenklassen

Richtig interessant wird das Matching aber erst mit den Zeichenklassen. Im einfachsten Fall werden diese durch eckige Klammern repräsentiert, also z.B. „[abc]“ oder „[0-9]“. „[abc]+“ würde beispielsweise auf alle unsere bisher genannten Zeichenketten zutreffen, denn alle enthalten eine mehr oder weniger lange Folge von a's, b's oder c's. Und „[0-9]+,[0-9]+“ trifft auf jede Dezimalzahl in deutscher Schreibweise zu, die mindestens eine Nachkommastelle hat, z..B. „1,0“.

Zeichenklassen für Fortgeschrittene

„[^abc]“

bedeutet nicht „a“, „b“ oder „c“, also Ersetzen von „[^abc]+“ in „bbbY“ durch „X“ würde liefern „bbbX“.

„[a-zA-Z]“

„a“ bis „z“ oder „A“ bis „Z“, inklusive (Bereich)

„[a-d[m-p]]“

„a“ bis „d“, oder „m“ bis „p“: „[a-dm-p]“ (Vereinigung)

„[a-z&&[def]]“

„d“, „e“, oder „f“ (Durchschnitt)

„[a-z&&[^bc]]“

„a“ bis „z“, außer „b“ und „c“: „[ad-z]“ (Subtraktion)

„[a-z&&[^m-p]]“

„a“ bis „z“, und nicht „m“ bis „p“: „[a-lq-z]“ ((Subtraktion)

Vordefiniertes

Für einzelne Zeichen oder ganze Zeichenklassen gibt es vordefinierte Ausdrücke, die meistens mit einem „\“ (Backslash) beginnen.

Vordefinierte Zeichen

\\

Das Backslash-Zeichen

\0n

Das Zeichen mit Oktal-Wert 0n (0 <= n <= 7)

\0nn

Das Zeichen mit Oktal-Wert 0nn (0 <= n <= 7)

\0mnn

Das Zeichen mit Oktal-Wert 0mnn (0 <= m <= 3, 0 <= n <= 7)

\xhh

Das Zeichen mit Hexadezimal-Wert 0xhh

\uhhhh

Das Zeichen mit Hexadezimal-Wert 0xhhhh

\t

Das Tabulator-Zeichen ('\u0009')

\n

Das Zeichen für „neue Zeile“ („newline“, '\u000A')

\r

Das Zeichen für Wagen-Rücklauf („carriage-return“, '\u000D')

\f

Das Zeichen für Seitenvorschub („form-feed“, '\u000C')

\a

Das Zeichen für einen Piepser („Glocke“, „alert“, „bell“, ('\u0007'))

\e

Das Escape-Zeichen ('\u001B')

\cx

Das zu x entsprechende CTRL-Zeichen. „\ca“ entspricht also dem Drücken der Umschalttaste „STRG“ (auf deutschen Tastaturen, engl. „CTRL“ für „control“) und dann dem „A“ (Beispiel: „\cj“ - oder „\011“ - wäre das Tabulator-Zeichen.)

Vordefinierte Zeichenklassen

.

Jedes Zeichen (je nach Einstellung des sogenannten „Dotall-Flags“ fällt unter JEDES Zeichen auch die Zeilenschaltung)

\d

Digit: Eine Ziffer: [0-9] (Achtung! Englische Dezimalzahlen können auch noch einen „.“ enthalten, Suchstring wäre dann etwa „\d+\.?\d*“.)

\D

KEINE Ziffer: [^0-9]

\s

Space: Leerraum: [ \t\n\x0B\f\r]

\S

Nicht-Leerraum: [^\s]

\w

Word. Wort-Zeichen: [a-zA-Z_0-9] (Daraus bestehen üblicherweise Variablennamen, für deutsche Texte fehlen hier die Umlaute äö...!)

\W

Nicht-Wort-Zeichen: [^\w]

POSIX-Zeichenklassen (nur US-ASCII, Vorsicht in Deutschland, wegen Umlauten usw.!)

\p{Lower}

Kleinbuchstabe: [a-z]

\p{Upper}

Grossbuchstabe: [A-Z]

\p{ASCII}

Alle ASCII-Zeichen:[\x00-\x7F]

\p{Alpha}

Alphabetische Zeichen:[\p{Lower}\p{Upper}]

\p{Digit}

Dezimalziffern: [0-9]

\p{Alnum}

Alphanumerische Zeichen:[\p{Alpha}\p{Digit}]

\p{Punct}

Zeichensetzung: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

\p{Graph}

Ein sichtbares Zeichen: [\p{Alnum}\p{Punct}]

\p{Print}

Ein druckbares Zeichen: [\p{Graph}\x20]

\p{Blank}

Leerzeichen oder Tabulator: [ \t]

\p{Cntrl}

Ein Controlzeichen (deutsch: STRG, Steuerzeichen): [\x00-\x1F\x7F]

\p{XDigit}

Hexadezimalziffern: [0-9a-fA-F]

\p{Space}

Leerraum: [ \t\n\x0B\f\r]

java.lang.Character Klassen (einfache java Zeichen)

\p{javaLowerCase}

Äquivalent zu java.lang.Character.isLowerCase()

\p{javaUpperCase}

Äquivalent zu java.lang.Character.isUpperCase()

\p{javaWhitespace}

Äquivalent zu java.lang.Character.isWhitespace()

\p{javaMirrored}

Äquivalent zu java.lang.Character.isMirrored()

Begrenzungs-Zeichen

^

Beginn einer Zeile

$

Ende einer Zeile

\b

Wort-Grenze (Achtung! Findet auch den „_“!)

\B

Nicht-Wort-Grenze

\A

Beginn der Eingabe

\G

Das Ende des vorigen Treffers

\Z

Ende der Eingabe bis auf das letzte Ende-Zeichen, falls vorhanden

\z

Ende der Eingabe

Spezielle Konstrukte:

(?:X)

X, eine nicht-erfassende (nicht mitzählende) Gruppe (engl. „non-capturing group“). Normalerweise bilden Klammern (Teil-) Ausdrücke, auf die man sich mit „$1“ bis „$9“ beziehen kann („$0“ bezeichnet den kompletten gefundenen Ausdruck). Beispiel: Wir wollen „abcXXXdef“ durch „abcdef“ ersetzen. Wir könnten das beispielsweise, indem wir „(abc).{3}(def)“ suchen und durch „$1$2“ ersetzen. „abc“ und „def“ könnten dabei auch irgend etwas Variables sein.

(?idmsux-idmsux)

Nichts, aber setzt die Flags i d m s u x an – aus.

Bedeutung der Flags:

i

caseInsensitiv = ignoriere Gross-klein

d

Unix-Lines = Unix-Zeilenschaltungen: In diesem Modus wird nur das „\n“ als Zeilenschaltung erkannt.

m

multiline = „mehrzeilig“: Normalerweise bilden „^“ und „$“ nur Treffer am Anfang und Ende der Eingabe; im multiline-Modus gilt das für Zeilenanfang und -ende. Schalten Sie den multiline-Modus nicht ein, wenn Sie nach einem mehrzeiligen Text suchen wollen! Benutzen Sie „\s+“, um nach Leerraum zu suchen (inclusive der Zeilenschaltung und unabhängig vom Betriebssystem)!

s

dotall = Punkt (dot) steht für alles (all) (also auch für Zeilenschaltungen)

u

unicode = Gross-klein entsprechend Unicode (sollte man besonders in Deutschland zusammen mit dem Flag i einschalten)

x

comments = Kommentare (und Leerzeichen) erlaubt. Kommentare beginnen mit einem „#“ und gehen bis zum Ende der Zeile.

Wir merken uns:

„\\“

brauchen wir unter Windoof bei Verzeichnisnamen. (Einfacher geht’s, wenn man den ganzen Verzeichnisnamen in „\Q“ und „\E“ einschließt („Quotation“ und „End“) , also beispielsweise „\QC:\Dokumente und Einstellungen\...\Eigene Dateien\E“.)

„\s+“

oder (noch besser) „\p{javaWhitespace}+“ bezeichnet einen beliebig langen Leerraum

„\w+“

einen Variablennamen (mit etwaigem Unterstrich, aber ohne Umlaute)

„\.“

ist ein Punkt

„.*“

ist eine beliebige (unter Umständen leere) Zeichenfolge

„\p{XDigit}{2,4}“

oder „[0-9a-fA-F]{2,4}“ bezeichnen Hexadezimal-Zahlen. Fehler bei Hexadezimal-Zahlen findet man beispielsweise mit „\s+[0-9a-fA-F]{3}[ \t\n\x0B\f\r\.;]+“.


Wer noch mehr wissen möchte, dem sei das Internet empfohlen, insbesondere mal eine Suche zu „java patterns regexp“ oder Gucken auf „http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html“.



Falls ich irgendwo Unsinn erzählt habe, was nicht ganz auszuschließen ist, da ich selbst noch Anfänger in Bezug auf regexp bin, bitte Mail an: eumel100@web.de



Counter

Harald K., E-Mail: eumel100@web.de