Jeder kann coden / Programmieren & TicTacToe / C# Einführung
Reguläre Ausdrücke¶
Reguläre Ausdrücke (Regex): Grundlagen¶
Reguläre Ausdrücke (Regex) sind Muster, die zur Beschreibung von Text verwendet werden, um bestimmte Zeichenfolgen zu suchen, zu validieren, zu extrahieren oder zu manipulieren. Sie bestehen aus Literalen, Metazeichen und Operatoren.
Hauptbestandteile von Regex:¶
Literale:
- Zeichen wie
a
,b
,1
,.
repräsentieren sich selbst. - Beispiel:
abc
entspricht genau "abc".
- Zeichen wie
Metazeichen:
- Zeichen mit spezieller Bedeutung, z. B.:
.
: Beliebiges Zeichen (außer Zeilenumbruch)^
: Start einer Zeile$
: Ende einer Zeile*
: 0 oder mehr Wiederholungen+
: 1 oder mehr Wiederholungen?
: 0 oder 1 Vorkommen|
: Oder-Verknüpfung\
: Escape-Zeichen[ ]
: Zeichenklassen( )
: Gruppierung
- Zeichen mit spezieller Bedeutung, z. B.:
Quantifizierer:
{n}
: Genau n Wiederholungen{n,}
: Mindestens n Wiederholungen{n,m}
: Zwischen n und m Wiederholungen
Zeichenklassen:
[abc]
: Entsprichta
,b
oderc
[^abc]
: Entspricht keinema
,b
oderc
[a-z]
: Entspricht jedem Buchstaben vona
bisz
\d
: Entspricht einer Ziffer (0-9
)\w
: Entspricht einem alphanumerischen Zeichen (a-z
,A-Z
,0-9
,_
)\s
: Entspricht einem Leerzeichen
Gruppen und Rückverweise:
(abc)
: Gruppiertabc
\1
: Verweist auf die erste Gruppe
Regex-Flavors¶
Es gibt verschiedene Regex-Engines ("Flavors"), die sich in Syntax und Funktionalität leicht unterscheiden:
POSIX:
- Einfacher und standardisiert, oft in Unix-Tools wie
grep
odersed
verwendet. - Beispiel:
[[:digit:]]
für Ziffern.
- Einfacher und standardisiert, oft in Unix-Tools wie
Perl Compatible Regular Expressions (PCRE):
- Sehr mächtig, weit verbreitet in Programmiersprachen wie PHP, JavaScript und Python.
ECMAScript:
- Wird in JavaScript und Webbrowsern verwendet.
- Unterstützt weniger Features als PCRE.
.NET Regex (C#):
- Basierend auf PCRE, aber mit zusätzlichen Features wie
RegexOptions
und Named Groups.
- Basierend auf PCRE, aber mit zusätzlichen Features wie
Oniguruma:
- Wird in Ruby verwendet, bietet erweiterte Funktionalität.
Verwendung von Regex in C#¶
In C# bietet die Klasse System.Text.RegularExpressions.Regex
eine leistungsstarke Implementierung von regulären Ausdrücken.
Grundlegende Methoden der Regex-Klasse:¶
IsMatch
:- Überprüft, ob ein Muster mit einer Zeichenkette übereinstimmt.
string pattern = @"^\d+$"; // Nur Ziffern string input = "12345"; bool isMatch = Regex.IsMatch(input, pattern); Console.WriteLine(isMatch); // True
Match
:- Gibt das erste Vorkommen zurück, das mit dem Muster übereinstimmt.
Match match = Regex.Match("abc123", @"\d+"); Console.WriteLine(match.Value); // 123
Matches
:- Gibt alle Übereinstimmungen in einer Sammlung zurück.
MatchCollection matches = Regex.Matches("a1b2c3", @"\d"); foreach (Match match in matches) { Console.WriteLine(match.Value); // 1, 2, 3 }
Replace
:- Ersetzt Übereinstimmungen mit einem angegebenen Wert.
string result = Regex.Replace("abc123", @"\d", "#"); Console.WriteLine(result); // abc###
Split
:- Teilt eine Zeichenkette anhand eines Regex-Musters.
string[] parts = Regex.Split("a1b2c3", @"\d"); foreach (string part in parts) { Console.WriteLine(part); // a, b, c }
Regex-Optionen:¶
Die RegexOptions
-Enumeration in C# ermöglicht erweiterte Konfigurationen:
RegexOptions.IgnoreCase
: Groß-/Kleinschreibung ignorieren.RegexOptions.Multiline
:^
und$
gelten für jede Zeile.RegexOptions.Singleline
:.
schließt Zeilenumbrüche ein.RegexOptions.Compiled
: Kompiliert den Regex für bessere Leistung.RegexOptions.CultureInvariant
: Kulturunabhängige Vergleiche.
Beispiel:
using System.Text.RegularExpressions;
string pattern = @"\bword\b";
string input = "Word, word, WORD!";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
bool isMatch = regex.IsMatch(input);
Console.WriteLine(isMatch); // True
True
Erklärung¶
In C# steht \b
für eine Wortgrenze. Es markiert die Position zwischen einem Wortzeichen (\w
) und einem Nicht-Wortzeichen. Es wird verwendet, um sicherzustellen, dass ein Muster nur an den Grenzen von Wörtern erkannt wird, ohne Teil eines längeren Wortes zu sein.
Beispiele in der Praxis:¶
Validierung einer E-Mail-Adresse:
string pattern = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"; string email = "test@example.com"; Console.WriteLine(Regex.IsMatch(email, pattern)); // True
Extrahieren von Zahlen:
string input = "abc123xyz"; MatchCollection matches = Regex.Matches(input, @"\d+"); foreach (Match match in matches) { Console.WriteLine(match.Value); // 123 }
Ersetzen von Leerzeichen:
string input = "a b c d"; string result = Regex.Replace(input, @"\s+", " "); Console.WriteLine(result); // a b c d
Zusammenfassung:¶
Reguläre Ausdrücke bieten in C# vielseitige Möglichkeiten, Text zu manipulieren und zu analysieren. Durch die Kombination von leistungsstarken Methoden und RegexOptions können Entwickler präzise und effiziente Muster anwenden. Das Verständnis der Syntax und Flavors hilft dabei, Regex korrekt und effektiv einzusetzen.
Cheatsheet reguläre Ausdrücke in C#¶
Erweiterte Funktionen und Tipps¶
1. Named Groups (Benannte Gruppen):¶
- Benannte Gruppen erleichtern die Arbeit mit komplexen Regex, indem sie bestimmte Teile des Musters benennen.
- Beispiel:
string pattern = @"(?<Protocol>https?)://(?<Domain>[^/]+)"; string input = "https://example.com"; Match match = Regex.Match(input, pattern); if (match.Success) { Console.WriteLine($"Protocol: {match.Groups["Protocol"].Value}"); Console.WriteLine($"Domain: {match.Groups["Domain"].Value}"); }
2. Lookahead und Lookbehind:¶
- Lookahead: Überprüft, ob ein bestimmtes Muster nach der aktuellen Position folgt, ohne es zu konsumieren.
- Lookbehind: Überprüft, ob ein Muster vor der aktuellen Position liegt.
- Beispiel (Lookahead):
string pattern = @"\d+(?= dollars)"; string input = "I have 100 dollars."; Match match = Regex.Match(input, pattern); Console.WriteLine(match.Value); // 100
- Beispiel (Lookbehind):
string pattern = @"(?<=\$)\d+"; string input = "Price: $200."; Match match = Regex.Match(input, pattern); Console.WriteLine(match.Value); // 200
3. Regex-Kommentar-Modus:¶
- Mit
RegexOptions.IgnorePatternWhitespace
kannst du einen Regex besser lesbar machen, indem du Kommentare und Leerzeichen einfügst. - Beispiel:
string pattern = @" ^ # Anfang der Zeichenkette (?<Protocol>https?):// # Protokoll (?<Domain>[^/]+) # Domain $ # Ende der Zeichenkette "; Regex regex = new Regex(pattern, RegexOptions.IgnorePatternWhitespace);
4. Performance-Optimierung:¶
- Regex-Kompilierung:
RegexOptions.Compiled
kompiliert den regulären Ausdruck in MSIL (Intermediate Language), was die Performance bei wiederholter Verwendung verbessert.- Beispiel:
Regex regex = new Regex(@"^\d+$", RegexOptions.Compiled);
- Caching:
- Die
Regex
-Klasse cached automatisch die letzten regulären Ausdrücke. Man sollte also unnötiges Neuerstellen von Regex-Objekten vermeiden.
- Die
5. Escape-Sequenzen und Raw Strings:¶
- Da Backslashes (
\
) in C# als Escape-Zeichen verwendet werden, ist es oft nützlich,@
vor der Zeichenfolge zu verwenden, um rohe Strings zu erstellen. - Beispiel:
string pattern = @"\d+";
- Ohne
@
müsste der Backslash verdoppelt werden:string pattern = "\\d+";
6. Debugging von Regex:¶
- Online-Tools:
- Tools wie regex101 oder RegexStorm helfen beim Testen und Erklären von regulären Ausdrücken.
- Regex-Evaluierung in C#:
- Mit Breakpoints und
Regex.Match()
kannst du während des Debuggens prüfen, welche Teile des Regex zutreffen.
- Mit Breakpoints und
7. Regex-Einschränkungen und Fehlerquellen:¶
- Lesbarkeit:
- Lange und komplexe Regex können schwer wartbar sein. Verwende Kommentare, benannte Gruppen und teile komplexe Muster in kleinere Abschnitte.
- Overfitting:
- Ein Regex sollte nicht zu spezifisch sein, da kleine Änderungen im Text (z. B. ein zusätzliches Leerzeichen) sonst zu unerwartetem Verhalten führen können.
- Backtracking:
- Exzessives Backtracking (bei z. B. übermäßig allgemeinen oder verschachtelten Mustern) kann die Performance stark beeinträchtigen. Verwende präzise Quantifizierer.
Praktische Szenarien für Regex:¶
Passwortvalidierung:
- Sicherstellen, dass ein Passwort mindestens 8 Zeichen, eine Zahl und ein Sonderzeichen enthält:
string pattern = @"^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$"; string password = "Test@123"; Console.WriteLine(Regex.IsMatch(password, pattern)); // True
- Sicherstellen, dass ein Passwort mindestens 8 Zeichen, eine Zahl und ein Sonderzeichen enthält:
Log-Analyse:
- Extrahieren von IP-Adressen aus Log-Dateien:
string pattern = @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"; string logs = "User connected from 192.168.1.1"; MatchCollection matches = Regex.Matches(logs, pattern); foreach (Match match in matches) { Console.WriteLine(match.Value); // 192.168.1.1 }
- Extrahieren von IP-Adressen aus Log-Dateien:
Datenextraktion:
- Herausziehen von Telefonnummern:
string pattern = @"\+?\d{1,3}[-.\s]?\(?\d+\)?[-.\s]?\d+[-.\s]?\d+"; string text = "Contact me at +1 (555) 123-4567 or 555-987-6543."; MatchCollection matches = Regex.Matches(text, pattern); foreach (Match match in matches) { Console.WriteLine(match.Value); // +1 (555) 123-4567, 555-987-6543 }
- Herausziehen von Telefonnummern:
Zusammenfassung:¶
- Reguläre Ausdrücke sind mächtig, aber komplex. Es lohnt sich, ein gutes Verständnis der grundlegenden Syntax und der erweiterten Features zu entwickeln.
- In C# erleichtert die
Regex
-Klasse durch benannte Gruppen, Regex-Optionen und Methoden wieMatch
,Replace
oderSplit
die Arbeit mit Text. - Beachte Performance-Aspekte, besonders bei großen Datenmengen oder komplexen Mustern.
- Verwende Debugging-Tools, um Regex besser zu verstehen und zu optimieren.