Reguläre Ausdrücke in Kotlin mit Beispielen: in der Praxis
\n\nReguläre Ausdrücke (regex) sind ein mächtiges Werkzeug für die Arbeit mit Zeichenketten. In Kotlin sind sie auf Basis der Java-Klassen Pattern und Matcher implementiert, wobei die Sprache jedoch eigene praktische Erweiterungen und syntaktischen Zucker hinzufügt. In diesem Artikel werden wir anhand realer Beispiele untersuchen, wie man reguläre Ausdrücke in Kotlin verwendet: von der einfachen Suche bis zum Ersetzen und Aufteilen von Zeichenketten.
Grundlagen der Syntax: Erstellung und Kompilierung
\n\nIn Kotlin kann ein regulärer Ausdruck auf zwei Arten erstellt werden: über die Klasse Regex oder mit einem String, der das Muster enthält. Die erste Methode ist vorzuziehen, da sie mehr Methoden bietet.
// Methode 1: über die Klasse Regex\nval regex = Regex("\\\\d+") // eine oder mehrere Ziffern\n\n// Methode 2: über einen String (nicht empfohlen für komplexe Ausdrücke)\nval pattern = "\\\\d+".toRegex()\n\nBeachten Sie den doppelten Escape-Backslash: \\\\d ist die Escape-Sequenz für Java/Kotlin, um das Zeichen \\d im String zu erhalten. Zur Vereinfachung unterstützt Kotlin Raw Strings (dreifache Anführungszeichen """), bei denen kein Escaping erforderlich ist:
val regex = Regex("""\\d+""") // Raw String – Backslashes müssen nicht verdoppelt werden\n\nMan kann auch Flags hinzufügen, z.B. RegexOption.IGNORE_CASE:
val regex = Regex("kotlin", RegexOption.IGNORE_CASE)\n\nSuchen und Prüfen auf Übereinstimmungen
\n\nDie häufigsten Operationen sind das Prüfen, ob ein String eine Teilzeichenkette gemäß einem Muster enthält, und das Finden aller Übereinstimmungen.
\n\nPrüfen auf Vorhandensein einer Übereinstimmung: containsMatchIn
\n\nval text = "Meine Nummer: 123-45-678"\nval digitRegex = Regex("""\\d+""")\n\nif (digitRegex.containsMatchIn(text)) {\n println("Der Text enthält Ziffern!")\n}\n\nSuchen der ersten Übereinstimmung: find
\n\nval result = digitRegex.find(text)\nprintln(result?.value) // Gibt aus: 123\n\nSuchen aller Übereinstimmungen: findAll
\n\nval allMatches = digitRegex.findAll(text)\nallMatches.forEach { match ->\n println("Gefunden: ${match.value}") // 123, 45, 678\n}\n\nDie Methode findAll gibt eine Sequenz von MatchResult-Objekten zurück. Jedes dieser Objekte enthält nicht nur die Übereinstimmung selbst (.value), sondern auch ihre Position im String (.range).
Arbeiten mit Erfassungsgruppen
\n\nErfassungsgruppen sind Teile des Musters, die in runde Klammern gesetzt werden. Sie ermöglichen das Extrahieren bestimmter Datenfragmente. Beispielsweise zerlegen wir eine E-Mail in Benutzername und Domain:
\n\nval email = "user@example.com"\nval emailRegex = Regex("""(.+)@(.+)""")\nval matchResult = emailRegex.find(email)\n\nif (matchResult != null) {\n val (username, domain) = matchResult.destructured\n println("Benutzername: $username") // user\n println("Domain: $domain") // example.com\n}\n\nDie Konstruktion destructured zerlegt die Gruppen bequem in Variablen. Bei mehreren Gruppen kann man über den Index darauf zugreifen:
val fullMatch = matchResult.value // user@example.com\nval group1 = matchResult.groupValues[1] // user\nval group2 = matchResult.groupValues[2] // example.com\n\nBenannte Gruppen (Kotlin 1.7+)
\n\nAb Kotlin 1.7 können benannte Gruppen verwendet werden:
\n\nval namedRegex = Regex("""(?<name>\\w+)@(?<domain>\\w+\\.\\w+)""")\nval match = namedRegex.find("contact@kotlin.org")\nif (match != null) {\n println(match.groups["name"]?.value) // contact\n println(match.groups["domain"]?.value) // kotlin.org\n}\n\nText ersetzen mit replace
\n\nDie Methode replace ermöglicht das Ersetzen aller Übereinstimmungen durch eine neue Zeichenkette. Im Ersetzungsmuster kann man auf Erfassungsgruppen verweisen, z.B.