Reguläre Ausdrücke in C++ mit Beispielen: In der Praxis
\n\nReguläre Ausdrücke (regex) sind ein mächtiges Werkzeug zur Textverarbeitung, mit dem Sie Zeichenketten nach komplexen Mustern suchen, ersetzen und überprüfen können. In C++ wurde die Unterstützung für reguläre Ausdrücke mit dem Standard C++11 durch die Bibliothek <regex> eingeführt. In diesem Artikel werden wir uns ansehen, wie man std::regex in der Praxis einsetzt: von einfachen Überprüfungen bis hin zur Datenextraktion und Textersetzung.
Das Material ist sowohl für Anfänger nützlich, die gerade erst C++ kennenlernen, als auch für erfahrene Entwickler, die ihr Wissen auffrischen möchten. Wir werden die wichtigsten Funktionen behandeln: std::regex_match, std::regex_search und std::regex_replace, sowie die Arbeit mit Erfassungsgruppen.
Hauptkomponenten der Bibliothek <regex>
\n\nBevor wir zu den Beispielen übergehen, schauen wir uns die wichtigsten Klassen und Funktionen an:
\n\n- \n
- std::regex — die Klasse, die den regulären Ausdruck selbst (das Muster) darstellt. Sie wird aus einer Zeichenkette mit dem Muster und einem optionalen Grammatik-Flag (standardmäßig ECMAScript) erstellt. \n
- std::smatch — ein Container zum Speichern von Suchergebnissen (für Zeichenketten vom Typ
std::string). Das Gegenstück iststd::cmatchfür C-Zeichenketten. \n - std::regex_match — prüft, ob die gesamte Zeichenkette vollständig mit dem Muster übereinstimmt. \n
- std::regex_search — sucht an einer beliebigen Stelle in der Zeichenkette nach einer Teilzeichenkette, die dem Muster entspricht. \n
- std::regex_replace — ersetzt alle Übereinstimmungen mit dem Muster durch eine angegebene Zeichenkette (mit Unterstützung für Rückverweise). \n
Alle Funktionen akzeptieren Flags zur Steuerung des Verhaltens (z. B. std::regex_constants::icase für die Groß-/Kleinschreibung-unabhängige Suche).
Beispiel 1: Überprüfung einer Zeichenkette auf Übereinstimmung mit einem Muster (std::regex_match)
\n\nDie einfachste Aufgabe besteht darin, zu prüfen, ob eine Zeichenkette einem bestimmten Format entspricht. Prüfen wir zum Beispiel, ob eine Zeichenkette eine gültige E-Mail-Adresse ist (vereinfachte Version):
\n\n#include <iostream>\n#include <regex>\n#include <string>\n\nint main() {\n std::string email = "user@example.com";\n // Muster zur Überprüfung einer E-Mail (vereinfacht)\n std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})");\n\n if (std::regex_match(email, pattern)) {\n std::cout << "E-Mail ist gültig." << std::endl;\n } else {\n std::cout << "E-Mail ist ungültig." << std::endl;\n }\n\n // Prüfung auf eine ungültige E-Mail\n std::string bad_email = "user@.com";\n if (std::regex_match(bad_email, pattern)) {\n std::cout << "E-Mail ist gültig." << std::endl;\n } else {\n std::cout << "E-Mail ist ungültig." << std::endl;\n }\n\n return 0;\n}\n\nAusgabe:
\nE-Mail ist gültig.\nE-Mail ist ungültig.\n\nErklärung:
\n- \n
- Wir verwenden ein rohes Zeichenkettenliteral
R"(...)", um Backslashes nicht escapen zu müssen. \n - Die Funktion
std::regex_matchgibttruenur dann zurück, wenn die gesamte Zeichenkette vollständig mit dem Muster übereinstimmt. \n - Das Muster
[a-zA-Z0-9._%+-]+bedeutet "ein oder mehr Zeichen aus der angegebenen Menge". \n
Beispiel 2: Suche nach einer Teilzeichenkette und Datenextraktion (std::regex_search)
\n\nOft muss man nicht nur prüfen, sondern alle Vorkommen eines Musters finden und Teile der Zeichenkette extrahieren. Dazu wird std::regex_search in einer Schleife verwendet. Im folgenden Beispiel finden wir alle Telefonnummern im Format +7-XXX-XXX-XX-XX in einem Text und extrahieren die Vorwahl:
#include <iostream>\n#include <regex>\n#include <string>\n\nint main() {\n std::string text = "Kontakte: +7-495-123-45-67 und +7-916-987-65-43. Zusatznummer: +7-495-111-22-33.";\n // Muster: +7-Vorwahl(3 Ziffern)-... (Erfassungsgruppen für Vorwahl und Rest)\n std::rege