Laden...

[Artikel] Regex-Tutorial

Erstellt von webstarg vor 16 Jahren Letzter Beitrag vor 7 Jahren 267.510 Views
W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren
[Artikel] Regex-Tutorial

:::

Hallo Community,

mein Regex-Tutorial ist fertig.

Das Tutorial ist sowohl im PDF-Format (empfohlen) als auch im BBCode-Format (im nächsten Post) verfügbar.

Ich hoffe, das Tutorial ist einigermaßen einsteigerfreundlich und verständlich.

Ich freue mich über jede Art von Feedback. 🙂

Viel Spaß beim Lesen des Tutorial!
webstarg

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

Tutorial zu Regex

[Aktuelle BBC-Code-Version]

1. Was ist Regex?
**Regex **ist die Abkürzung für **„Regular Expressions“, **zu Deutsch: „Reguläre Ausdrücke“.
Es ist eine Zeichenkette, die der Beschreibung von Mengen beziehungsweise Untermengen von Zeichenketten mit Hilfe bestimmter syntaktischer Regeln dient. (Wikipedia)

Regex ist ein mächtiges Mittel zum Validieren und Bearbeiten von Zeichenketten.

2. Verwendung von Regex in C#
Um Regex in einem C#-Programm nutzen zu können, muss zunächst der Namespace System.Text.RegularExpressions eingebunden werden.
Dies geschieht, indem wir vor die Klasse

using System.Text.RegularExpressions;

schreiben.

Getestet werden können diese Ausdrücke, indem wir zunächst eine Instanz von Regex erstellen:

Regex myRegex = new Regex([Pattern]);

Unter **Pattern **versteht man das Muster, nach welchem die Zeichenfolgen überprüft werden sollen. Das Pattern kann beispielsweise beschreiben, dass nur Zeichen von A – Z verwendet werden dürfen. Oder alle Buchstaben des Alphabets, Zahlen sowie der Strichpunkt. Anstelle von [Pattern] übergeben wir dem Konstruktor das Muster.
Um Zahlen zuzulassen, wäre folgendes Pattern geeignet: ^[0-9]*$
Auf die Zeichenfolgen werde ich aber später noch näher eingehen.

Anmerkung: Es empfiehlt sich, vor dem einleitenden Anführungszeichen des Pattern-Strings ein @-Zeichen zu setzen. Dies bewirkt, dass im String vorkommende Anführungszeichen und Backslash weniger verwirrend angegeben werden können. Anführungszeichen verdoppelt man (ohne Verwendung von @ vor dem String müsste man \“ für die Verwendung des Anführungszeichen schreiben), Backslash können normal angegeben werden (wenn ohne @ doppelt: \). (Dies trifft nicht zu, wenn das Pattern zur Laufzeit definiert wird (z. B. Eingabe des Patterns in ein Textfeld während das Programm ausgeführt wird).)

Die Instanz von Regex generieren wir folgendermaßen:

Regex myRegex = new Regex(„^[0-9]*$”);

Um eine Zeichenfolge, die in textBox1 steht, nach diesem Muster zu überprüfen, wäre folgende Befehlszeile von Nöten:

bool bedingungWahr = myRegex.IsMatch(textBox1.Text);

3. Funktionen von Regex
Die Klasse Regex bietet folgende Möglichkeiten:
Methode: Match
o String nach einem Vorkommen des regulären Ausdrucks (Pattern) durchsuchen und eine Extrahierung des getroffenen Textteils aus der Eigenschaft Match.Value auslesen
o Rückgabewerttyp: Match

Methode: Matches
o String nach allen Vorkommen des regulären Ausdrucks durchsuchen
o Rückgabewerttyp: MatchCollection

Methode: IsMatch
o String auf Gültigkeit bezüglich eines Musters überprüfen
o Rückgabewerttyp: Bool

Methode: Replace
o Zeichenfolgen in einem String ersetzen
o Rückgabewerttyp: String

Methode: Split
o Zum Splitten (Aufteilen) eines String
o Rückgabewerttyp: String[]

Anmerkung: Zu jeder Methode gibt es mehrere Überladungen. So kann beispielsweise mit RegexOptions.IgnoreCase angegeben werden, dass zwischen Groß- und Kleinschreibung nicht unterschieden wird. Bitte beachten Sie, dass wenn diese Regex-Option nicht eingestellt ist, zwischen Groß- und Kleinschreibung unterschieden wird.

In diesem Tutorial werde ich hauptsächlich auf die Syntax von Regex eingehen und mich auf die IsMatch-Methode beziehen.

Damit beim Üben nicht bei jeder Änderung des Patterns das gesamte Programm neu kompiliert werden muss, kann man sein Pattern mit Hilfe von On-the-fly-Testprogrammen testen:
So gibt es das Programm Regex-Lab (On-the-fly-Regex-Tester) kostenlos zum Herunterladen.
Das Programm Espresso (engl.) analysiert reguläre Ausdrücke und stellt diese strukturiert dar.
Wer an einem Computer ohne installiertem .NET-Framework ist, kann Regex auf meiner Seite ausprobieren: http://odwn.brinkster.net/regex.aspx

4. Syntax von Regex
Wieso beschreibt die Zeichenfolge ^[0-9]*$ als Pattern, dass nur Ziffern als gültige Zeichen anerkannt sind?

Kommen wir zur Syntax von Regex, mit welcher das Muster beschrieben werden kann.

4.1 Einfachstes Pattern
Auch ein Wort oder ein Zeichen ist bereits ein gültiges Pattern (Muster). So erlaubt das Beispiel-Pattern Zeichen unter anderem „Zeichen“, „Zeichenfolge“, „DruckZeichen“, „Westliche Zeichenkodierung“ usw. Alle Strings, die dieses Wort enthalten, liefern bei der Validierung mit diesem Pattern eine positive Rückantwort.

4.2 Patternbeginn und -Ende
Das Zeichen ^ kennzeichnet, wenn es zu Beginn des Patterns steht, dass der zu durchsuchende String ab Beginn dem Muster entsprechen muss. Dieses Zeichen wird auch Zeichenanker genannt.
Das Ende kennzeichnet man mit dem Dollar-Zeichen $.

Beispiele:
^Zeichen erlaubt alle Strings, die mit Zeichen beginnen, also z. B. „Zeichenkodierung“, nicht aber „DruckZeichen“.
Soll ein gültiger String mit Zeichen enden, so wäre das Pattern Zeichen$.
Nur das Wort „Zeichen“ als einzig gültige Zeichenfolge wird mit ^Zeichen$ beschrieben.
Auch ^$ ist ein gültiges Pattern: Es beschreibt eine leere Zeichenfolge.

4.3 Zeichenauswahlen / Zeichenbereiche
Innerhalb der eckigen Klammern können sich Zeichenauswahlen (verschiedene Zeichen) und/oder Zeichenbereiche befinden:
So erlaubt der die Zeichenauswahl [ASDF] einen der Großbuchstaben A S D F.

[0-9] steht für die Ziffern von 0 bis 9 (wobei 0 und 9 eingeschlossen sind). Der Bindestrich charakterisiert, dass es sich um einen Bereich handelt. (Wenn der Bindestrich aber direkt nach dem Zeichen [ oder als letztes Zeichen vor ] (also vor oder nach dem Bereich oder der Zeichenfolge) stehen würde, dann wäre der Bindestrich als Zeichen und nicht als „von-bis“ zu verstehen.)
[a-z] würde die Zeichen von a bis z beinhalten, [c-f] die zwischen c und f mit c und f inklusive.

In den Klammern können man auch mehrere Bereiche angeben werden:
So beschreibt das Pattern [A-Za-z0-9] sowohl Groß- als auch Kleinbuchstaben sowie Ziffern. Zu beachten ist, dass ä, ö, ü, ß nicht in [a-z] liegen.

Zeichenauswahlen und Bereiche können auch kombiniert werden.
[A-Za-zäöüßÄÖÜ] würde demnach alle Zeichen von A bis Z sowie Ä, Ö, Ü (auch als Kleinbuchstaben) akzeptieren. Oder [1-35-9] (Kombination [1-3] und [5-9]) erlaubt 1, 2, 3, 5, 6, 7, 8 und 9.

Diese Patternteile innerhalb der eckigen Klammern [] gelten jedoch nur für ein einzelnes Zeichen – sofern nicht durch Quantoren (siehe 4.5 Quantoren) hinter den Klammern anders angegeben.
Das Pattern ^[A-Za-zäöüßÄÖÜ]$ würde demnach zwar den einzelnen Buchstaben A oder s oder ü zulassen, nicht aber „As“ oder „sDk“ oder „sdfkl“.

4.4 Negationen
Wenn das Zeichen ^ nicht zu Beginn des Patterns verwendet wird, so steht es für eine Negation und bedeutet ungleich.
^[^A-Z]*$ würde alle Zeichen außer Großbuchstaben zulassen (alles außer die Zeichen A-Z).

4.5 Quantoren
Um dann zwei Großbuchstaben zu erlauben könnte man ^[A-Z][A-Z]$ verwenden. Was aber, wenn wir hundert Ziffern erlauben möchten? Hundert mal [0-9] schreiben?
Dann bzw. auch schon bei zweimaliger Wiederholung verwendet man Quantoren. Quantoren geben die Anzahl der Wiederholungen an.

Es gibt folgende Quantoren:
?: Der voranstehende Ausdruck ist optional, er kann einmal vorkommen, muss es aber nicht, d. h. der Ausdruck kommt null- oder einmal vor. (Dies entspricht {0,1})
+: Der voranstehende Ausdruck muss mindestens einmal vorkommen, darf aber auch mehrfach vorkommen. (Dies entspricht {1,})
*: Der voranstehende Ausdruck darf beliebig oft (auch keinmal) vorkommen. (Dies entspricht {0,})
{n}: Der voranstehende Ausdruck muss exakt n-mal vorkommen.
{min,}: Der voranstehende Ausdruck muss mindestens min-mal vorkommen.
{,max}: Der voranstehende Ausdruck darf maximal max-mal vorkommen (wird von .NET nicht unterstützt).
{min,max}: Der voranstehende Ausdruck muss mindestens min-mal und darf maximal max-mal vorkommen.
(Wikipedia)

Genau 100 Ziffern hintereinander als Muster zu definieren, könnte man so bewerkstelligen: ^[0-9]{100}$
Der Quantor steht hinter dem Bereich, für welchen er gelten soll.

4.6 Vordefinierte Zeichenklassen
Um nicht jedes Mal [0-9], [a-zA-Z], usw. schreiben zu müssen, kann man statt diesen Bereichen die Kurzschreibweise für vordefinierte Zeichenklassen angeben.

Wichtige Zeichenklassen sind:
\d: eine Ziffer [0-9]
\D: ein Zeichen, das keine Ziffer ist, also [\d]
\w: ein Buchstabe, eine Ziffer oder der Unterstrich, also [a-zA-Z_0-9] (und evtl. weitere Buchstaben, z. B. Umlaute)
\W: ein Zeichen, das weder Buchstabe noch Zahl noch Unterstrich ist, also [
\w]
\s: Whitespace; meistens die Klasse der Steuerzeichen \f, \n, \r, \t und \v
\S: ein Zeichen, das kein Whitespace ist [^\s]
(Wikipedia)

In neueren Implementationen von Regex sind zusätzlich nachfolgende POSIX-Klassen möglich.
Bemerkung: Die Regex-Engine von .NET unterstützt keine POSIX-Klassen!
[:alnum:]: Alphanumerische Zeichen: [:alpha:] und [:digit:].
[:alpha:]: Buchstaben: [:lower:] und [:upper:].
[:blank:]: Leerzeichen und Tabulator.
[:cntrl:]: Steuerzeichen. Im ASCII sind das die Zeichen 00 bis 1F, und 7F (DEL).
[:digit:]: Ziffern: 0, 1, 2,... bis 9.
[:graph:]: Graphische Zeichen: [:alnum:] und [:punct:].
[:lower:]: Kleinbuchstaben: nicht notwendigerweise nur von a bis z.
[:print:]: Druckbare Zeichen: [:alnum:], [:punct:] und Leerzeichen.
[:punct:]: Zeichen wie: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ .
[:space:]: Whitespace: Horizontaler und vertikaler Tabulator, Zeilen- und Seitenvorschub, Wagenrücklauf und Leerzeichen.
[:upper:]: Großbuchstaben: nicht notwendigerweise nur von A bis Z.
[:xdigit:]: Hexadezimale Ziffern: 0 bis 9, A bis F, a bis f.
(Wikipedia)

4.7 Escape-Zeichen
Der Punkt ist ein Sonderfall. Normalerweise steht der Punkt für ein beliebiges Zeichen. Er kann auch für eine neue Zeile stehen. Ist der Punkt als solcher gemeint, so muss man diesen „escaped“ verwenden, also indem man vor dem Punkt (dem zu escapenden Zeichen) einen Backslash einfügt: .
Unter „Escapen“ versteht man, dass die Meta-Bedeutung eines Zeichens aufgehoben wird und dass das Zeichen als solches dargestellt wird.
Um folgende Zeichen zu verwenden, muss man diese auch escapen: \ ( ) [ { | * ? + ^ $ . # [Leerzeichen] (Einige Zeichen müssen nur in einem bestimmten Kontext escaped werden.)
Aufzupassen gilt auch bei der Verwendung folgender beiden Zeichen: „ \ (siehe 2. Verwendung von Regex in C# auf Seite 3)

Zum Escapen bietet Regex die statische Methode Escape. Diese Methode, der man einen String als Parameter übergibt, versieht einen minimalen Satz von Metazeichen mit Escape-Zeichen und gibt das Ergebnis als String zurück. Das Gegenteil erledigt die statische Methode Unescape.

4.8 Weitere Zeichen
^: Zeilenanfang (nicht zu verwechseln mit der Negation ^ bei der Zeichenauswahl mittels [ und ]).
$: je nach Kontext für Zeilen- oder Stringende, wobei noch ein \n folgen darf. Das tatsächliche Ende wird von \z gematcht.
: hebt gegebenenfalls die Metabedeutung des nächsten Zeichens auf. Beispielsweise lässt der Ausdruck „(A*)+“ die Zeichenketten „A*“, „AA“ usw. zu. Auf diese Weise lässt sich auch ein Punkt „.“ mit . suchen.
\b: steht für die leere Zeichenkette am Wortanfang oder am Wortende.
\B: steht für die leere Zeichenkette, die nicht den Anfang oder das Ende eines Wortes bildet.
&lt;: steht für die leere Zeichenkette am Wortanfang.
&gt;: steht für die leere Zeichenkette am Wortende.
(Wikipedia)

4.9 Gruppierungen
Gruppierungen sind Zusammenfassungen von Ausdrücken in runden Klammern. Diese ermöglichen Wiederverwendbarkeit dieser Teilausdrücke und das Einbauen von Alternativen („ODER“; siehe 4.10 Alternativen auf Seite 8).

^001$ erlaubt nur „001“, ^(001)*$ würde „001001001“ erlauben, da der Quantor * auf die Gruppierung angewandt wird und somit die drei Zeichen in der Klammer beliebig oft wiederholt werden dürfen.

Gruppierungen können mit [Gruppierungsindex] aufgerufen werden. (Anmerkung: Dieser Index ist nicht nullbasiert.)
Beispiel: ^(136[0-3])[A-Z]\1$ akzeptiert: „1360A1360“, „1361A1361“, ..., „1361A1363“, …, „1360B1360“, …, „1363Z1363“;
\1 verweist (referenziert) auf den Inhalt der ersten Klammer. Daher muss an der Stelle von \1 das stehen, was von der 1. Gruppierung gematcht wurde.
Dies ist nützlich, wenn man überprüfen möchte, ob beispielsweise zwei gleiche Wörter (hintereinander) vorkommen.

Anstatt die Gruppierungen anhand des Index aufzurufen, kann ihnen ein Namen zugewiesen werden. Der Gruppenname darf keine Satzzeichen enthalten und nicht mit einer Zahl beginnen.
Den Gruppennamen definiert man, indem man nach Öffnen der runden Klammer ?<[Gruppenname]> schreibt. Der Aufruf erfolgt mit \k<[Gruppenname]>. [Gruppenname] ersetzt man mit dem gewünschten Namen.

Beispiel:
Erste Verwendung der Gruppe und Namensdefiniton: ^(?<DeutscheSonderzeichen>[äöüÄÖÜß])$
Aufruf: \k<DeutscheSonderzeichen>

Das Zurückgreifen auf Gruppierungen nennt man „Backtracking“.

Welches Zeichen eine Gruppe gematch hat, kann aus der Property Match.Groups gelesen werden, falls man die Methode Match verwendet hat.

4.10 Alternativen
Alternativen werden mit dem „Oder“-Zeichen in Regex aufgezählt. Das Oder wird mit dem Zeichen | (Alt Gr + <) dargestellt.
Beispiel: (001|005|1008) erlaubt „001“ oder „005“ oder „1008“.

Selbstverständlich können Alternativen auch verschachtelt werden.
Bsp: (Airbus (A350|A380)|Boeing (747|787))

4.11 Kommentare
Kommentare gibt man folgendermaßen an: (?#[Kommentar])
Beispiel: ^[0-9]{2}(?#2 Ziffern erforderlich)$
Kommentare können vor allem bei längeren und verschachtelten Ausdrücken sinnvoll sein, da man sich später beim Überarbeiten des Patterns leichter tut.

4.12 Gieriges Verhalten
Von gierigem (engl. greedy) Verhalten spricht man, wenn von einem regulären Ausdruck die längste passende Zeichenkette ausgewählt wird. Dies ist nicht immer erwünscht und kann deshalb auch deaktiviert werden.

Beispiel:
Zu überprüfender String: „12312431231235“

Gieriges Verhalten:
o Pattern: ^1.1
o Ergebnis von Match(@“^1.1“).Value: „12312431231"
o Erst mit dem letzten Vorkommen (im Suchstring) des Zeichens hinter .
im Pattern verwendet die Regex-Engine dieses als nachfolgendes Zeichen; vorherige Zeichen, die auf das Zeichen nach .
zutreffen, werden als beliebiges Zeichen (Punkt) interpretiert. Der Punkt hat alle außer dem letzten auf das Ende zutreffenden Zeichen „gefressen“.

Genügsames Verhalten:
o Nicht gieriges Ergebnis wäre: „1231“
o Hier spricht man von genügsamen Verhalten, da die letzte Ziffer von „1231“, die eins, auf die 1 nach dem * zutrifft.

Es gibt 2 Möglichkeiten „genügsames“ Verhalten zu verwenden:
Eine Möglichkeit ist, hinter dem Quantor das Zeichen ? anzuhängen. Also wird das obere Beispiel zu: ^1.*?1. Aus Performance-Gründen ist dies aber nicht empfehlenswert, da der Regex-Interpreter jedes Mal zurückspringen und die „Backreference“ überprüfen muss.
Die zweite Möglichkeit wäre eine Umformung des oberen Beispiels zu folgendem Pattern: ^1[^1]*1 (1. Zeichen eine 1, beliebig viele „Nicht-Eins“-Zeichen im Mittelteil und die 1 als Ende)

4.13 Positive und negative Lookarounds
Anmerkung zu Kapitel 4.13 und 4.14: Dieses und das folgende Kapitel sind fortgeschrittene Konzepte, gehen tiefer in die Materie Regex ein und sind dementsprechend etwas komplizierter. Diese beiden Kapitel sind eher an Fortgeschrittene gerichtet. Sie sollten diese Kapitel nur lesen, wenn Sie die vorherigen verstanden haben. (Um zu überprüfen, ob Sie Regex verstanden haben, können Sie auf Seite 12 bei 6. Übungen üben. Das Wissen über diese beiden Kapitel ist zum Lösen der Fragestellungen nicht notwendig.)

Die Lookarounds stellen die Leistungsfähigkeit von Regex nochmals unter Beweis. Man unterscheidet zwischen Lookbehinds und Lookaheads, wobei diese wiederum in positive und negative Lookarounds unterteilbar sind.

Mit Lookarounds lässt sich festlegen, dass eine Zeichenfolge nur gematcht wird, wenn sich direkt vorher und/oder nachher eine bestimmte Zeichenfolge befindet. Da diese Bedingungszeichenfolge nicht in das Suchergebnis (Regex.Value) aufgenommen wird, spricht man auch von „zero-width-assertions“.
Die [Bedingung] (auch „Behauptung“ genannt) wird als regulärer Ausdruck angegeben, wobei die Verwendung von Quantoren (*, +, {0,5}, …) jedoch nicht möglich ist.

4.13.1 Lookbehinds
Lookbehinds beziehen sich auf Bereiche, die vor der momentan untersuchten Stelle im zu durchsuchenden Text liegen und somit bereits hinter uns liegen (deshalb „Lookbehind“).
Vor dem eigentlichen Suchmuster wird nach einem weiteren Suchmuster gesucht. Nur wenn das weitere Suchmuster erfolgreich gefunden wird (positiv) bzw. erfolgreich nicht gefunden wird (negativ), gibt es einen Treffer.

Positive Lookbehinds behaupten, dass (direkt) vor einem Ausdruck etwas stehen soll. Die Bedingung wird vor dem Ausdruck mit (?≤[Bedingung]) angegeben.

Negative Lookbehind-Behauptungen, die festlegen, dass (direkt) vor einem Ausdruck etwas nicht stehen soll, werden mit (?<![Bedingung]) beschrieben, das vor den Ausdruck gestellt wird.

4.13.2 Lookaheads
Lookaheads sind das Gegenteil von Lookbehinds und beziehen sich auf Bereiche, die nach der aktuell untersuchten Stelle liegen (deshalb „Lookahead“).

Positive Lookaheads behaupten, dass nach einem Ausdruck etwas Bestimmtes stehen soll. Die Angabe erfolgt mit dem Ausdruck (?=[Bedingung]).

Negative Lookahead-Behauptungen lauten (?![Bedingung]). Direkt nach der untersuchten Stelle soll eine Zeichenfolge nicht vorkommen.

4.13.3 Zusammenfassung Lookarounds

Syntax       Positiv            Negativ	   
Lookbehind   (?<=[Bedingung])   (?<![Bedingung])	   
Lookahead    (?=[Bedingung])    (?![Bedingung])

Positive Lookbehind-Bedingung: (?≤de)
Triff nur („Matche“ nur), wenn vorher „de“ steht.
Negative Lookbehind-Bedingung: (?<!de)
Triff nur, wenn vorher nicht „de“ steht.
Positive Lookahead-Bedingung: (?=de)
Triff nur, wenn nachher “de” steht.
Negative Lookahead-Bedingung (?!de)
Triff nur, wenn nachher nicht “de” steht.

4.13.4 Beispiele zu Lookarounds

(?≤0)[0-9]{3}(?!€)
o (?<0): Lookbehind, positiv (vor [0-9]{3} soll eine „0“ stehen)
o [0-9]{3}: Ausdruck im Mittelteil (kein Lookaround!) (\d{3} würde das gleiche beschreiben)
o (?!€): Lookahead, negativ (nachher soll nicht „€“ stehen)
(?<![a-eA-M]).server1(?=.us)
o (?<![a-eA-M]): Lookbehind, negative (vor .server1 soll weder ein Kleinbuchstabe von a-e noch ein Großbuchstabe von A-M stehen)
o .server1: Mittelteil (. steht für einen escapten Punkt)
o (?=.us): Lookahead, positive (nach .server1 soll “.us” stehen)

4.14 RegexMatchEvaluator
RegexMatchEvaluator stellt eine Erweiterung der Regex-Methode Replace dar.

Um den RegexMatchEvaluator zu verwenden, benötigt man eine Instanz von MatchEvaluator. Diese Klasse befindet sich im gleichen Namespace wie Regex und wird folgendermaßen instanziert:
MatchEvaluator myEvaluator = new MatchEvaluator([Methode]);

Außerdem braucht man eine Methode mit einem String als Rückgabewert:

public string ReplaceMatch(Match m)
{
	[IF-Anweisungen]
	return [Ersetzung];
}

(Sollten Sie dieses Beispiel in einer Konsolenanwendung ausprobieren, so fügen Sie im Methodenkopf vor „string“ das Schlüsselwort static ein.)

Den Parameter [Methode] bei der Instanzierung ersetzt man in diesem Beispiel mit ReplaceMatch, da dies der Name der Methode mit String-Rückgabe ist.

Das Pattern, das wir bisher dem Regex-Konstruktor bekannt gegeben haben, wird erst jetzt der Replace-Methode übergeben. Das Ersetzen mit der statischen Replace-Methode sieht allgemein so aus:

string [Variablenname] = Regex.Replace([Zu ersetzender String], [Pattern], [MatchEvaluator-Instanz]);

Beispiel:
In diesem einfachen Beispiel werden alle Beistriche durch eine leere Zeichenkette ("") ersetzt. Da der Ersatzstring unabhängig vom Treffer gleich bleibt, ist in diesem Fall die Verwendung von MatchEvaluator nicht besonders sinnvoll, denn die gleiche Aufgabe ließe sich auch einfacher mit der Replace-Methode durchführen.

MatchEvaluator myEvaluator = new MatchEvaluator(ReplaceMatch);
string output = Regex.Replace("H,a,l,l,o", ",", myEvaluator);

Und die Methode:

public string ReplaceMatch(Match m)
{
	return "";
}

Die Variable output würde „Hallo“ enthalten, da von der Methode ReplaceMatch jeder gefundene Beistrich mit einer leeren Zeichenkette ersetzt wird.
Lösung mit der Replace-Methode von Regex:

Regex.Replace("H,a,l,l,o", ",", "");

(Allgemein:

Regex.Replace([ZuErsetzen], [Pattern], [Ersatz]);

)

Sinnvoll wird der MatchEvaluator, wenn wir Suchtreffer mit einem flexiblen String ersetzen möchten.

Beispiel:

  • Ziel: Wir wollen alle „ae“ zum Umlaut „ä“, alle „oe“ zu … umwandeln
  • Wir erstellen eine Instanz von MatchEvaluator mit dem Namen myEvaluator und übergeben dem Konstruktor den Namen der folgenden Methode:
  • Methode:
public string ReplaceMethode(Match m)
{
 	switch (m.Value)
 	{
 		case "ae":
 		return "ä";
		case "oe":
 		return "ö";
		case "ue":
 		return "ü";
 		case "Ae":
 		return "Ä";
		case "Oe":
 		return "Ö";
		case "Ue":
 		return "Ü";
 		default:
 		return "";
 	}
}

(Den default-Zweig im Switch-Case-Konstrukt brauchen wir, damit alle Codepfade einen Wert zurückgeben, wie es der Compiler haben will.)

  • Durchführen der Ersetzung mit der Replace-Methode (Pattern: [aou]e):
    string ersetzterString = myRegex.Replace("Franz faehrt von Muenchen nach Oesterreich, um einen Baer zu suchen.", "[aou]e", myEvaluator, RegexOptions.IgnoreCase);
  • String nach der Ersetzung: Franz fährt von München nach Österreich, um einen Bär zu suchen.
  • Erklärung: Alle ae, oe und ue im String werden je nach Treffer mit ä, ö oder ü ersetzt. Aufgrund von RegexOptions.CaseInsensitive trifft Regex auch Ae, Oe und Ue. (Bei jedem Treffer (Match) wird die Methode ReplaceMethode aufgerufen und der Treffer mit dem Rückgabewert der Methode ersetzt.)

(Weitere sinnvolle Ersetzungen wären, dass die Klasse, in der sich die Methode befindet, eine statische Int-Variable mit dem Ausgangswert 0 enthält. Diese Variable wird bei jedem Aufruf der Methode inkrementiert (um den Wert 1 erhöht) und als Ersetzungsstring zurückgegeben. Siehe: http://msdn2.microsoft.com/de-de/library/system.text.regularexpressions.matchevaluator(VS.80).aspx)

5. Tipps zur Performance
Einige Tipps, um die Performance zu verbessern:Alternativen sind ziemlich rechenintensiv und sollten deshalb so selten wie möglich verwendet werden. Wenn sie nicht vermeidbar sind, so sollte die häufigste Möglichkeit als erste gelistet werden. Man sollte soviel Text wie möglich explizit und ohne Alternativen angeben, da dies eine effektive innere Optimierung ermöglicht. (Beispiel: xxxxx* statt x{5,} oder S(ams|onn)tag statt (Samstag|Sonntag)) Klammern sollten nur dort benutzt werden, wo sie wirklich nötig sind. Vordefinierte Zeichenklassen sollten benutzt werden. Falls vom Sinn her möglich sollte man auf jeden Fall den Pattern mit ^ beginnen. (http://www.jex-treme.de/forum/thread.php?threadid=18064)

6. Übungen zu Regex
Und nun einige Übungen: Bei jeder der 17 Übungen sollen Sie ein Pattern schreiben, das auf die Fragestellung zutrifft. Zur Verdeutlichung der Fragestellung hat jede Frage ein Beispiel. Die Lösungen stehen direkt unter der Frage und sind meist erklärt. Die Übungen sind nach Schwierigkeitsgrad gestaffelt.

++Fragestellung: ++Pattern, das eine 4-stellige Zahl erlaubt, wobei das erste Zeichen (der Zahl) ungleich "0" sein muss (Bsp: 7344)
Lösung: ^[1-9][0-9]{3}$
Beschreibung der Lösung:
^ und $, damit sich das Muster auf den gesamten String bezieht
[1-9]: damit ein Zeichen aus 1, 2, 3, ..., 9 gewählt wird
[0-9]: damit ein Zeichen von 0 bis 9 (inklusive) gewählt wird (Alternativen: [:digit:], \d)
{3}: damit [0-9] 3-mal wiederholt wird ([0-9]{3} entspricht [0-9][0-9][0-9])

Wort mit 4 Zeichen (Bsp: Haus)
^[a-zA-Z][a-z]{3}$
[a-zA-Z]: als erstes Zeichen einen Groß- oder Kleinbuchstaben (gleichbedeutend wäre: [a-zA-Z]{1})
[a-z]{3}: 3-mal Kleinbuchstaben sind vorgeschrieben

Nur Buchstaben "a" und "b" enthalten (Bsp: abaababbaaa)
^[ab]$
[ab]
: Beliebig oft (oder auch nie) darf a oder b vorkommen
Binärzahlen (längenmäßig unbeschränkt) (Bsp: 00100101)
^[01]*$

Wort mit Großbuchstaben zu Beginn, das mit "en" endet (Bsp: Tannen)
^[A-Z][a-z]en$
[A-Z]: für den Großbuchstaben am Wortanfang
[a-z]
: beliebig viele Kleinbuchstaben
en: mit en muss der String enden.

Ziffer Strich Ziffer Strich Ziffer (Bsp: 1-7-6)
^[0-9]-[0-9]-[0-9]$

  • (2. Vorkommen): Bindestrich wird als solcher verwendet, da er nicht innerhalb der eckigen Klammern ist
    (Weitere Möglichkeit: ^([0-9]-){2}[0-9]$)

"Wort", das nur aus Kleinbuchstaben besteht und keinen Selbstlaut enthält (Bsp: dkfs)
^[b-df-hj-np-tv-z]*$

Zahl (1. Stelle ungleich "0") mit Einheit (" Stück") (Bsp: 60 Stück)
^[1-9][0-9]* Stück$
[1-9]: eine Ziffer von 1 bis 9, damit die 1. Stelle nicht 0 sein kann
[0-9]*: beliebig viele (auch kein Vorkommen möglich) Ziffern
Stück: muss am Ende stehen

Smiley: 1. Zeichen ":" oder ";"; 2. Zeichen "-"; 3. Zeichen "(" oder ")" oder "|"; (Bsp: 😉
^[:;]-[()|]$
[:;]: Doppelpunkt oder Strichpunkt als 1. Zeichen
-: Bindestrich als 2. Zeichen
[()|]: ( oder ) oder | als 3. Zeichen

Zahl zwischen -750 und 750 (wenn Zahl positiv, dann kein Vorzeichen; die Zahl kann auch zwei- oder einstellig sein; ohne führende Nullen) (Bsp: 411)
^-?(750|7[0-4][0-9]|[1-6][0-9]{2}|[1-9]?[0-9])$
-?: Zeichen „-„ kann vorkommen
750: 750
|7[0-4][0-9]: oder 700 bis 749 möglich
|[1-6][0-9]{2}: oder 100 bis 699 (beginnt mit 1 bis 6, danach zwei beliebige Ziffern)
|[1-9]?[0-9]: oder 0-99 (beginnt optional mit 1 bis 9, danach eine beliebige Ziffer)

Dreistellige Zahl von -750 bis 750 (wenn Zahl positiv, dann kein Vorzeichen; ohne führende Nullen) (Bsp: 747)
^-?(750|7[0-4][0-9]|[1-6][0-9]{2})$

4-stellig mit Buchstaben "A" an 1. Stelle gefolgt von Zahl [300;399], oder Buchstabe "B" zu Beginn gefolgt von Zahl [737;747;...;787] (Zahl: 1. Stelle "7", 2. Stelle 3, 4, 5, 6, 7 oder 8, 3. Stelle 7) (Bsp: A380)
^(A3[0-9]{2}|B7[3-8]7)$
A3[0-9]{2}: „A3“ + zwei mal Ziffer von 0 - 9
|B7[3-8]7: oder „B7“ + Ziffer von 3 – 8 + „7“

Wort mit mind. 2 gleichen aufeinander folgenden Zeichen bzw. Buchstaben (Bsp: Schiff)
([a-zA-Z])\1
[a-zA-Z]: Buchstabe
\1: Zeichen, welches in der 1. Gruppierung gematcht wurde

Uhrzeit im Format 00:00:00 (Bsp: 16:41:33)
^(2[0-3]|[0-1]?[0-9])(:[0-5][0-9]){2}$
(2[0-3]|[0-1]?[0-9]):
2[0-3]: „2“ gefolgt von einer der Ziffern 1, 2, oder 3 (für 20, 21, 22, 23 Uhr)
|[0-1]?[0-9]: oder Ziffer 0 oder 1 gefolgt von einer Ziffer (für 00 Uhr bis 19 Uhr)
(:[0-5][0-9]){2}:
:: Doppelpunkt
[0-5][0-9]: Minuten/Sekunden 00 bis 59
{2}: wird genau 2-mal wiederholt (einmal für die Minuten, einmal für die Sekunden)

E-Mail-Adresse (ohne Umlaute und ß) (Bsp: bill_gates@googlemail.com)
^[a-zA-Z0-9_-]{1,}[a-zA-Z0-9_-.][a-zA-Z0-9_-]{1,}@[a-zA-Z0-9_-]{2,}.[a-z]{2,4}$
[a-zA-Z0-9_-]{1,}[a-zA-Z0-9_-.]
[a-zA-Z0-9_-]{1,}: Groß-, Kleinbuchstaben, Ziffern, Bodenstrich, Bindestrich als Beginn und als letztes Zeichen vor dem @ erlaubt; zusätzlich zu diesen Zeichen ein Punkt in der Mitte erlaubt (Punkt darf also nicht am Beginn und als letztes Zeichen vor dem @ stehen)
@: @-Zeichen
.: Punkt als solcher und deshalb escaped
[a-z]{2,4}: für die 2 bis 4 Zeichen lange Toplevel-Domain (Bsp: de, com, info)
(und noch viele andere Lösungen (Microsoft-Lösung (in Microsoft Visual Studio Web Developer 2005 Express Edition): \w+([-+.']\w+)@\w+([-.]\w+).\w+([-.]\w+)*))

Internet-Adresse (ohne Umlaute und ß) (Bsp: http://www.google.de/)
^(https?://)?(www2?.)?[a-zA-Z0-9&-()$/]{2,}.[a-z]{2,4}/?$
(https?://)?: Fragezeichen nach https (Zeichen kann vorkommen) bezieht sich nur auf das vorhergehende Zeichen, das in diesem Fall das s ist; das Fragezeichen am Ende, welches hinter einer Gruppierung steht, bezieht sich auf die Gruppierung; erlaubt ist also: http:// oder https:// oder gar nichts
(www2?.)?: vorkommen kann: www. oder www2. oder gar nichts
[a-zA-Z0-9&-()$/]{2,}: erlaubte Zeichen für die Second-Level-Domain, wobei diese mindestens 2 Zeichen ({2,}) lang sein muss; ( und ) stehen für die offene und geschlossene runde Klammer als solche, da diese Klammern ansonsten als Gruppierung interpretiert werden
[a-z]{2,4}: Top-Level-Domain mit 2 – 4 Zeichen
/?: / als letztes Zeichen erlaubt
(und noch viele andere Lösungen (Microsoft-Lösung: http(s)?://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?))
Betrag in € (optional 2 Kommastellen), mit 1.000er-Trennzeichen (Bsp: 10.000,00 €)
^[0-9]{1,3}(.[0-9]{3})
(,[0-9]{2})?[ ]?€$
[0-9]{1,3}: eine bis maximal 3 Ziffern zu Beginn (wenn Zahl größer 999, dann stellen diese Ziffern die Ziffern vor dem 1. 1000er-Trennzeichen dar)
(.[0-9]{3})*:
.: steht für den Punkt; muss mit dem Backslash escaped werden (Punkt für Tausender-Trennzeichen benötigt)
[0-9]{3}: 3 Ziffern
*: diese Gruppierung kann 0 – unendlich mal vorkommen
(,[0-9]{2})?:
,: Komma
[0-9]{2}: 2 Ziffern für die 2 Kommastellen
?: diese Gruppierung kann 0 oder 1-mal vorkommen
[ ]?: Leerzeichen kann vorkommen
€: €-Zeichen als Ende

7. Weblinks
Seite zum Tutorial auf mycsharp.de: Feedback, Online-Version,
Veröffentlichung von neueren Versionen:
[Artikel] Regex-Tutorial
Wikipedia-Artikel zu Regex (deutsch):
Regex
Sehr gutes deutsches und einfach verständliches Tutorial:
http://www.danielfett.de/df_artikel_regex.html
Deutsches Tutorial:
http://regexp-evaluator.de/tutorial/
Deutsches Tutorial:
http://www.lrz-muenchen.de/services/schulung/unterlagen/regul/
Deutsches Tutorial in Tabellenform für Fortgeschrittene:
http://mojo-corp.de/regulaere_ausdruecke_c_sharp.html
Behandlung von Regex-Fehlermeldungen (deutsch):
http://regexp-evaluator.de/tutorial/fehlermeldungen/
Video-Clip im Microsoft Developer Netzwerk (MSDN) (deutsch):
http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=118760869
Englischsprachiger Artikel aus Wikipedia zu Regex:
Regular expression
Sehr gutes englisches Tutorial für Einsteiger auf Codeproject:
http://www.codeproject.com/dotnet/RegexTutorial.asp
Weiteres englisches Tutorial auf Codeproject:
http://www.codeproject.com/string/re.asp
Ausführliches englisches Tutorial zu Regex:
http://www.regular-expressions.info/tutorial.html
Informationen bei MSDN:[URL] [URL]http://msdn.microsoft.com/de-de/library/hs600312.aspx[/URL][/url]
Englische Webseite mit einer Sammlung von regulären Ausdrücken:
http://regexlib.com/default.aspx

10. Literatur
Um das letzte Quäntchen aus Regex herauszukitzeln, kann folgendes Buch empfohlen werden:
o „Reguläre Ausdrücke“ von Jeffrey E. F. Friedl, O'Reilly Verlag

© 2007-2009; webstarg.

T
194 Beiträge seit 2006
vor 16 Jahren

Hallo webstarg,

Dein Artikel finde ich sehr gut.

Einen Fehler habe ich aber gefunden:
4.14 -> Pattern = "[aou]e", nicht "aou[e]"

T
194 Beiträge seit 2006
vor 16 Jahren

Ein weiterer Fehler:

  1. Übungen
    > "Wort", das nur aus Kleinbuchstaben besteht und keinen Selbstlaut enthält (Bsp: dkfs)
    Die Lösung "^[^aeiou]*$" stimmt nicht.
W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

Vielen Dank!

Habe ich ausgebessert.
webstarg

(Neuer Pattern zu Übung 6: ^[b-df-hj-np-tv-z]*$)

M
6 Beiträge seit 2006
vor 16 Jahren

Unter 4.9 ist glaube ich auch ein Fehler.
Im Beispiel steht, dass "1363Z1363Z" auch der RegExp entspricht. Das "Z" am Ende ist aber zuviel.

Ansonsten sehr schönes Tutorial zum Thema. Vielen Dank!

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

@ MinusBrain: Vielen Dank, das stimmt natürlich. Habe ich ausgebessert.

grüße
webstarg

I
1.739 Beiträge seit 2005
vor 16 Jahren

Gute Arbeit.
Ein so allgemeinverständliches(naja: nach dem ersten Einstieg) und gleichzeitig tiefgehendes Tutorial ist selten.
Hat sicher Zeit gekostet, und ist hilfreich.
Was ein wenig fehlt ist die Einstiegshilfe(zB: Escape-Sequenz - was ist das, Regex - was ist das). Abgesehen davon find ich den Artikel sehr gelungen.

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

Original von ikaros
Gute Arbeit.
Ein so allgemeinverständliches(naja: nach dem ersten Einstieg) und gleichzeitig tiefgehendes Tutorial ist selten.

Danke.

Was ein wenig fehlt ist die Einstiegshilfe(zB: Escape-Sequenz - was ist das, Regex - was ist das).

Zu Regex gibt es bereits eine kurze Einleitung (Kapitel 1):

  1. Was ist Regex?
    Regex ist die Abkürzung für „Regular Expressions“, zu Deutsch: „Reguläre
    Ausdrücke“.
    Es ist eine Zeichenkette, die der Beschreibung von Mengen beziehungsweise
    Untermengen von Zeichenketten mit Hilfe bestimmter syntaktischer Regeln dient.
    (Wikipedia)

Regex ist ein mächtiges Mittel zum Validieren und Bearbeiten von Zeichenketten.

Gut, vielleicht etwas kurz. 😉

Die Escape-Sequenzen kann ich schon noch etwas ausbauen. Mache ich demnächst.

mfg
webstarg

699 Beiträge seit 2007
vor 16 Jahren

Hallo webstarg,

möchte Dir auch ein Lob für das umfangreiche Tutorial aussprechen.
Das dürfte einem Anfänger in der Materie sicher sehr helfen.

Wenn man dann aber mal Feuer gefangen hat, dann kann man fast nicht mehr anders 😉 dann ist sicher auch ein Buch hilfreich um auch das letzte Quäntchen aus der Regex zu kitzeln 😉

Genau dieses Buch möchte ich euch da mal empfehlen:

Reguläre Ausdrücke von Jeffrey E. F. Friedl aus dem O'Reilly Verlag.

Dies kann ich uneingeschränkt empfehlen.

Grüße Stephan

F
323 Beiträge seit 2007
vor 16 Jahren

Hallo!

Erstmal muss ich sagen, dass dieses Tutorial wirklich sehr gut ist. Mir hat es auf jeden Fall mehrere Stunden googlen erspart. Ich hoffe es wird auch weiterhin gepflegt von dir!

Eine Anmerkung hätte ich da noch:
Es ist ein grammatikalischer Fehler vorhanden. Bei Punkt 3 beim Punkt IsMatch. Ich glaube es müsste "eines" heißen oder?

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

Hallo!

@ all:
Das Tutorial wurde aktualisiert.

@ Froggi:

Erstmal muss ich sagen, dass dieses Tutorial wirklich sehr gut ist. Mir hat es auf jeden Fall mehrere Stunden googlen erspart. Ich hoffe es wird auch weiterhin gepflegt von dir!

Danke! Ja, ich werde es weiterhin pflegen.
Den Grammatikfehler habe ich übrigens berichtigt.

@ Stipo:
Auch danke für das Lob.
Ich habe mir erlaubt, deinen Buchtipp im Tutorial unter Punkt 8 (Literatur) einzufügen.

@ ikaros:
Beim Durchnehmen der Änderungen habe ich auch einen Blick auf den Punkt "Escape-Zeichen" geworfen. Eine kurze Erklärung zu Escape-Sequenzen ist bereits enthalten:

Unter „Escapen“ versteht man, dass die Meta-Bedeutung eines Zeichens aufgehoben wird und dass das Zeichen als solches dargestellt wird.

(Falls du es gerne ausführlicher hättest, kannst du mir gerne ein paar Sätze dazu senden, die ich dann einbauen würde.)

Danke für das viele Feedback.

Viele Grüße
webstarg

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

Sowohl die BBC-Code-Version als auch die PDF-Version habe ich aktualisiert.

**BBC-Code:***Rechtschreibfehler entfernt *Inhaltsverzeichnis entfernt (Seiten gibt es sowieso nicht)

**PDF-Version:***Rechtschreibfehler entfernt *Formatierungsfehler behoben *Seitenzahlen korrigiert und die Absatzvorlage Überschrift genommen und mit Word die Seitenzahlen erstellt, damit diese auch nach Bearbeitungen noch stimmen *Adresse von sämtlichen Links (anstatt den Anzeigenamen) angegeben (da man im PDF nicht auf die Links klicken kann)

webstarg

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

Beide Versionen wurden aktualisiert.

Alles was neu ist, ist eigentlich, dass jetzt ein Hinweis vorhanden ist, dass Regex POSIX-Klassen nicht unterstützt. (regex [:xdigit:]...)

mfg
webstarg

U
1.688 Beiträge seit 2007
vor 16 Jahren

Hallo,

die Pattern in 4.12 scheinen mir nicht zum String zu passen:

Zu überprüfender String: „12312431231235“

Gieriges Verhalten:
o Pattern: ^1.*1$
o Ergebnis von Match(@“^1.*1$“).Value: „12312431231"

Das '$' am Ende ist falsch, da der String ja nicht mit '1' aufhört.

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

Danke! Da ist mir wohl ein Fehler unterlaufen.

grüße
webstarg

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 16 Jahren

Beide Versionen wurden wieder aktualisiert.

**Änderungen:***Fehler im Beispiel zu 4.12 ausgebessert *Link zu meiner Regex-Testseite aktualisiert (Seite funktioniert jetzt) *Beispielsatz bei Erklärung eingefügt *weitere minimale Änderungen

Grüße
webstarg

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 15 Jahren

**Änderungen:***C#-Codestellen in der PDF-Datei auf Formatierung Visual Studio 2008 umgestaltet *In den Übungen das Muster zu den E-Mail-Adressen bearbeitet (Nun darf im Bereich vor dem @ auch ein . (Punkt) sein (außer am Beginn, vor dem @-Zeichen))

mfg
webstarg

B
1 Beiträge seit 2008
vor 15 Jahren

Hallo webstarg,

gutes Tutorial! Ich arbeite schon lange mit regulaeren Ausdruecken, habe aber
immer noch was gelernt. Super! 🙂

Den einzigen Punkt, den ich nicht gleich verstanden habe, ist 4.14 auf Seite 10.
Ich musste erst bis zum Beispiel mit den Umlauten weiterlesen, bis ich verstanden
habe, warum "eine Methode mit einem String als Rückgabe" gebraucht wird. Es
waere vielleicht hilfreich, hier direkt am Anfang einen Satz darueber zu verlieren,
wofuer die Methode gebraucht wird bzw. was sie macht. Es wuerde auch reichen,
vor dem Einfuehren der Methode "ReplaceMatch" zu schreiben, dass im
nachfolgenden Beispiel alle Kommata gegen Leerzeichen ersetzt werden sollen und
dass die Methode deshalb immer ein Leerzeichen zurueckgibt, egal was als Match
uebergeben wird.

Ich habe, glaube ich, auch Fehler gefunden: In Absatz 4.14.4 auf der gleichen
Seite steht unter dem zweiten Spiegelpunkt ".\server1", dass muss aber wohl
".server1" heissen.

Ausserdem muss es im gleichen Satz "Kleinbuchstabe" und "Großbuchstabe"
heissen, nicht "Kleinbuchstaben" und "Großbuchstaben".

Danke und viele Gruesse,

ballaballa1556

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 15 Jahren

Hallobalaballo1556,

dankeschön für dein Feedback. Ich werde mal durchgehen.

grüße
webstarg

Edit/Ergänzung: Ja, das ist ein Fehler. Werde ihn ausbessern. Und noch einen Fehler habe ich (indirekt durch dich 😉) gefunden: Auf 4.13.3 folgt 4.14.4

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 15 Jahren

Aktualisierungen:

PDF-Version 2.00 vom 13.08.2008:
[+] Hinzugefügt: Kapitel 2.1 Validieren von numerischen Benutzereingaben
[+] Hinzugefügt: Link zur Forumsseite des Tutorials auf mycsharp.de in Kapitel 7
[>] Überarbeitet: Gesamtes Tutorial sprachlich überarbeitet
[>] Ausgetauscht: Englischen MSDN-Link durch deutschen ersetzt
[>] Überarbeitet: Kapitel 4.14
[>] Überarbeitet: Teilweise Formatierung korrigiert und vereinheitlicht
[>] Überarbeitet: Tabelle in Kapitel 4.13.3 neu angeordnet
[!] Fehler entfernt: Unübersetzt hineinkopierten englischen Teilsatz übersetzt
[!] Fehler entfernt: Kapitel "4.14.4" ist eigentlich "4.13.4"
[!] Fehler entfernt: Grammatikfehler in Kapitel 4.13.4 korrigiert
[!] Fehler entfernt: Falsche Satzstellung in Kapitel 4.13.2 korrigiert
[!] Fehler entfernt: Verb kommt im Kapitel Übungen in einem Satz doppelt vor
[!] Fehler entfernt: Wortfolge kommt im Kapitel Übungen in einem Satz doppelt vor
[!] Fehler entfernt: Patternteil im Kapitel 4.13.4 korrigiert: ".\server1" durch ".server1" ersetzt
[!] Fehler entfernt: Pattern in Kapitel 4.3 korrigiert: "[A-Zaz-0-9]" durch "[A-Za-z0-9]" ersetzt

BBC-Code-Version 1.00i vom 13.08.2008:
[+] Hinzugefügt: Link zur Forumsseite des Tutorials auf mycsharp.de in Kapitel 7
[>] Überarbeitet: Kapitel 4.14
[>] Ausgetauscht: Englischen MSDN-Link durch deutschen ersetzt
[!] Fehler entfernt: Unübersetzt hineinkopierten englischen Teilsatz übersetzt
[!] Fehler entfernt: Kapitel "4.14.4" ist eigentlich "4.13.4"
[!] Fehler entfernt: Grammatikfehler in Kapitel 4.13.4 korrigiert
[!] Fehler entfernt: Falsche Satzstellung in Kapitel 4.13.2 korrigiert
[!] Fehler entfernt: Verb kommt im Kapitel Übungen in einem Satz doppelt vor
[!] Fehler entfernt: Wortfolge kommt im Kapitel Übungen in einem Satz doppelt vor
[!] Fehler entfernt: Patternteil im Kapitel 4.13.4 korrigiert: ".\server1" durch ".server1" ersetzt
[!] Fehler entfernt: Pattern in Kapitel 4.3 korrigiert: "[A-Zaz-0-9]" durch "[A-Za-z0-9]" ersetzt

Grüße
webstarg

J
130 Beiträge seit 2008
vor 15 Jahren

Super TUT 👍

danke für die gute Arbeit 🙂

**“DOH !” -Homer Simpson**
I
1.739 Beiträge seit 2005
vor 15 Jahren

Der Artikel wurde qualitativ(insbesondere Darstellung, in echter Qualitätt konnte kaum bemängelt werden) Abgeshen von leichten
Anfgsschwieririgkeiten sehr verbessert, und sehr viel Mühe wurde reingeesteckt.
Du bist gewachsen.

R
206 Beiträge seit 2007
vor 14 Jahren

Hi webstarg,

danke für den Artikel!

Hab noch nen kleinen Fehler in der PDF gefunden:

public string ReplaceMethode(Match m)
{
    switch (m.Value)
    {
        case "ae":
        return "ä";
        break;
        case "oe":
        return "ö";
        break;
        case "ue":
        return "ü";
        break;
        case "Ae":
        return "Ä";
        break;
        case "Oe": //HIER STEHT IN DER PDF "Ae"
        return "Ö";
        break;
        case "Ue":
        return "Ü";
        break;
        default:
        return "";
        break;
    }
}

Gruß,
Max

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 14 Jahren

@ Riv3r: Danke für den Hinweis, ich schaus mir an und korrigiere das gegebenenfalls.

grüße
webstarg

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 14 Jahren

Hallo,

ich habe nachgesehen und bemerkt, dass ich vergessen habe einige Versionen zu veröffentlichen (2.01, 2.10, 2.20).
Die aktuelle Version hat den von Riv3r bemerkten Fehler nicht mehr und ist am ersten Beitrag angehängt.

[Änderungen]
Version 2.20
[>] Überarbeitet: PDF wurde mit Microsoft Office erstellt (vorher: PDFCreator, welches das PDF auf Basis des PostScript-Ausdruckes von Word erstellt), daher sind nun alle internen (Inhaltsverzeichnis, Verweise) sowie externen Links anklickbar

Version 2.10
[>] Überarbeitet: Vermehrt Zeichenklassen (etwa \d statt [0-9]) in Beispielen und Übungen verwendet (da ich dies ja in "5. Tipps zur Performance" empfehle)
[>] Überarbeitet: In Kapitel 4.14 "[(IF-)Anweisungen]" mit "[Verzweigungen und Anweisungen]" ersetzt
[>] Überarbeitet: Nicht nennenswerte Ergänzungen, kleine Änderungen
[+] Hinzugefügt: Kapitel 2.2 "On-the-fly-Testprogramme" erstellt (Text aus Kapitel 3 "Funktionen von Regex" ausgegliedert
[>] Gliederung geändert: Kapitel 3 umbenannt in "Die Klasse Regex", Inhalt in 3.1 "Wichtige Methoden" verschoben
[+] Hinzugefügt: Kapitel 3.2 "RegexOptions"
[+] Hinzugefügt: In Kapitel 5 "Tipps zur Performance" Link zu myCSharp-Artikel hinzugefügt: Performance von Regex

Version 2.01
[!] Fehler entfernt: Im Quellcode bei Kapitel 4.14 einmal "Ae" mit "Oe" ausgetauscht
[/Änderungen]

Viele Grüße
webstarg

87 Beiträge seit 2006
vor 14 Jahren

Hi,
ein wirklich sehr guter Artikel. Ich glaub nun versteh ich Regex auch endlich mal. 😁

Einen Verbessungsvorschlag hätte ich dann, aber doch noch.

Die "breaks;" in der switch-Anweisung weglassen. Da vor dehnen ein "return [...];" kommt werden die eh nich benötig. Ferner sollten die Compiler-Warnungen erzeugen.

-->


public string ReplaceMethode(Match m)
{
	switch (m.Value)
	{
		case "ae":
			return "ä";
		case "oe":
			return "ö";
		case "ue":
			return "ü";
		case "Ae":
			return "Ä";
		case "Oe":
			return "Ö";
		case "Ue":
			return "Ü";
		default:
			return "";
	}
}

MfG

TiltonJH

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

W
webstarg Themenstarter:in
558 Beiträge seit 2006
vor 14 Jahren

@ TiltonJH: Ok, das mach ich. In der BBCode-Version gleich, die PDF-Version lade ich dann hoch, wenn sich mehrere Änderungen angesammelt haben.

grüße
webstarg

S
12 Beiträge seit 2009
vor 14 Jahren

Hei Super Tutorial!

Vielen Dank, konnte es gut gebrauchen 😮

Gruss Sayen

B
224 Beiträge seit 2009
vor 14 Jahren

Ist wirklich super gelungen, man findet hier einfach alles.

S
138 Beiträge seit 2006
vor 14 Jahren

Hallo, ich habe hier einen Fehler, denk ich zumindest mal:

E-Mail-Adresse (ohne Umlaute und ß) (Bsp:
>
)
^[a-zA-Z0-9_-]{1,}[a-zA-Z0-9_-.][a-zA-Z0-9_-]{1,}@[a-zA-Z0-9_-]{2,}.[a-z]{2,4}$
[a-zA-Z0-9_-]{1,}[a-zA-Z0-9_-.]
[a-zA-Z0-9_-]{1,}: Groß-, Kleinbuchstaben, Ziffern, Bodenstrich, Bindestrich als Beginn und als letztes Zeichen vor dem @ erlaubt; zusätzlich zu diesen Zeichen ein Punkt in der Mitte erlaubt (Punkt darf also nicht am Beginn und als letztes Zeichen vor dem @ stehen)
@: @-Zeichen
.: Punkt als solcher und deshalb escaped
[a-z]{2,4}: für die 2 bis 4 Zeichen lange Toplevel-Domain (Bsp: de, com, info)
(und noch viele andere Lösungen (Microsoft-Lösung (in Microsoft Visual Studio Web Developer 2005 Express Edition): \w+([-+.']\w+)@\w+([-.]\w+).\w+([-.]\w+)*))

wenn ich diese Expression verwenden ("^[a-zA-Z0-9_-]{1,}[a-zA-Z0-9_-.]*[a-zA-Z0-9_-]{1,}@[a-zA-Z0-9_-]{2,}.[a-z]{2,4}$") bekomme ich folgende Exception:

"^[a-zA-Z0-9_-]{1,}[a-zA-Z0-9_-.]*[a-zA-Z0-9_-]{1,}@[a-zA-Z0-9_-]{2,}.[a-z]{2,4}$" wird analysiert - [x-y]-Bereich in umgekehrter Reihenfolge.

Hab noch nicht wirklich eine Ahnung warum, weil eigentlich sieht das ganze ja recht logisch aus. Sobald ich einen / den Fehler gefunden habe, poste ich diesen.

S
138 Beiträge seit 2006
vor 14 Jahren

Hab die Ursache gefunden. Ich weiß zwar nich arum, aber der . hat etwas gestört.

Mittels Workaround hab ich jetzt folgendes:

^[a-zA-Z0-9_-]{1,}[**.a-zA-Z0-9_-]*[a-zA-Z0-9_-]{1,}@[.**a-zA-Z0-9_-]{2,}[a-z]{2,4}$

Ich weiß wirklich nicht warum es eine Rolle spielt, ob der Punkt am Anfang oder am Ende der Aufzählung ist, aber bitte...

Klappt jetzt auch super, weil die Lösung von Microsoft selber, lässt Umlaute durch und deswegen hab ich auf diese Variante zurückgreifen müssen.

mfg
deluxe

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo schillerdeluxe,

ob der Punkt am Anfang oder Ende steht oder irgendwo in der Mitte steht, spielt an sich keine Rolle. Der Punkt hat innerhalb von eckigen Klammern nicht mal sein übliche Sonderbedeutung, sondern steht auch ohne Backslash nur für sich selbst, also für einen Punkt und nicht für ein beliebiges Zeichen. Man kann den Backslash also einfach weglassen.

Das eigentlich Problem ist der Bindestrich, der wiederum nur innerhalb von Backslash seine bekannte Sonderbedeutung bekommt, sofern er nicht am Anfang oder am Ende steht. Dadurch, dass du den Punkt an den Anfang gesetzt hast, rückte der Bindestrich ans Ende und verlor seine Sonderbedeutung, was das Problem löste.

herbivore

S
789 Beiträge seit 2007
vor 13 Jahren

Perfekt...vielen Dank!

B
15 Beiträge seit 2010
vor 13 Jahren

Sauber, echt gute Arbeit, ich bin beeindruckt! 😃

Allerdings finde ich persönlich den Gebrauch des Wortes "Regex" im Text etwas gewöhnungsbedürftig.
Z.b.: 4. Syntax von Regex.
Ich bin jetzt in diesem Gebiet kein Experte, doch diese Formuliering finde ich etwas unschön. Gut, wenn man Regex als Abkürzung für die deutsche Übersetzung "Reguläre Ausdrücke" verwendet, passt's einigermaßen, wenn auch grammatikalisch nicht so ganz.
Klar, ich will nicht allzu pingelig sein, jeder versteht's, vielleicht könntest du am Anfang einen kurzen Hinweis geben (z.B. unter 1, "im folgenden Text steht Regex stellvertretend für 'Reguläre Ausdrücke'" oder so etwas in der Art).

C# Tipps und Tricks: http://csharp-tricks.blogspot.com/

6.911 Beiträge seit 2009
vor 13 Jahren

Hallo bloggeroli,

das steht indirekt ja eh da:

  1. Was ist Regex?
    Regex ist die Abkürzung für „Regular Expressions“, zu Deutsch: „Reguläre Ausdrücke“.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

T
8 Beiträge seit 2010
vor 13 Jahren

Hi webstarg!

WOW super Tutorial!
Hat mir sehr geholfen 👍

lg,
Wolfi

S
16 Beiträge seit 2011
vor 13 Jahren

Hallo webstarg,

vielen Dank für das Tutorial!
Es ist sehr kompakt und und gut verständlich!
Genau das, was ich gebraucht habe.

lg
Serpiano

W
56 Beiträge seit 2009
vor 12 Jahren

Hi,

ich fand das Tutorial sehr gut.

MfG Iwan

Alle haben gesagt es geht nicht, dann kam einer der hat das nicht gehört und hat es gemacht.

B
218 Beiträge seit 2012
vor 10 Jahren

Du beziehst ja deinen Inhalt auf das .NET Framework, richtig?

Dann sollte das hier abgeändert werden:

{,max}: Der voranstehende Ausdruck darf maximal max-mal vorkommen.

Das ist meines Wissens nach so nicht implementiert.

Hinweis von herbivore vor 10 Jahren

Danke für den Hinweis. Ich habe im den obigen Text dahinter geschrieben, dass dies von .NET nicht unterstützt wird.

A
15 Beiträge seit 2012
vor 10 Jahren

Hi,

erst einmal vielen Dank für das Tutorial.

Bei den Übungen ist mir bei der Aufgabe 10 (Zahl zwischen -750 und 750) aufgefallen, dass das Pattern aus der Lösung auch -000, -00, -0, 00 und 000 zulässt. Wenn statt
^-?(7[0-4]\d|750|[0-6]?\d{1,2})$ das Pattern
^(0$|-?([1-9]\d?|[1-6]\d{0,2}|7[0-4]\d|750))$ verwendet wird besteht das Problem nicht. Sprich es wird geprüft, ob die Eingabe = 0 oder Minus bzw. kein Zeichen und 1-99 oder 100-699 oder 700-749 oder 750 ist.

Ähnlich ist es bei Aufgabe 11 (dreistellige Zahl von -750 bis 750). Hier funktionieren auch -000 und 000.
Das Problem lässt sich beheben indem aus
^-?(7[0-4]\d|750|[0-6]\d{2})$
^-?(7[0-4]\d|750|[1-6]\d{2})$ wird.

Dann ist mir noch ein Schreibfehler im Abschnitt 4.13 Positive und negative Look arounds aufgefallen:
Lookarounds (auch Assertations genannt) stellen die die Leistungsfähigkeit von

Hinweis von herbivore vor 10 Jahren

Danke für den Hinweis. Ich habe die drei Punkte im Forum, aber nicht im PDF, korrigiert. Deinen ersten Patternvorschlag habe ich so geändert, dass auf jede der möglichen Zahlen immer nur genau eine der Alternativen matcht und dass -0 weiterhin zulässig ist, wobei letzteres zugegeben Geschmackssache ist.

64 Beiträge seit 2012
vor 10 Jahren

Vielen Dank für das super Tutorial. Immer wenn mir RegEx mal wieder über den Weg läuft zieht es mich hier hin 😉

Um RegEx "spielerisch" zu Lernen kann ich noch RegEx-Golf empfehlen:

http://regex.alf.nu/

Ziel ist es mit möglichts kurzen Statements alle nötigen Ausdrücke zu matchen, und die unnötigen Ausdrücke auszuschließen.

++Rekursion ++
(lat. , die) siehe Rekursion

S
14 Beiträge seit 2014
vor 9 Jahren

Hab noch einen Fehler gefunden.

  1. Übungen Nr. 6

Ziffer Strich Ziffer Strich Ziffer Strich (Bsp: 1-7-6)
^\d-\d-\d$

Ich denke das letzte Strich ist zuviel, zumindest wenn man dem Beispiel und der Lösung folgt.

Gruß
shufflekeks

Hinweis von herbivore vor 9 Jahren

Danke für den Hinweis. Ich habe das überzählige Auftreten des Wortes "Strich" im Aufgabentitel entfernt. Allerdings wie bisher auch nur im Forum, nicht im PDF.

S
3 Beiträge seit 2016
vor 7 Jahren

Danke für dieses Bemerkenswerte Regex Tutorial, dank diesen hab ich mir eine Frage gespart und enorm viel Code.

Wirklich gut und verständlich geschrieben, hat keine 5 Minuten gedauert da hatte ich meine Antwort. 👍