Wie zähle ich die Anzahl der Übereinstimmungen für einen Regex?

1. Übersicht

Reguläre Ausdrücke können für eine Vielzahl von Textverarbeitungsaufgaben verwendet werden, z. B. für Wortzählalgorithmen oder die Validierung von Texteingaben.

In diesem Tutorial sehen wir uns an, wie reguläre Ausdrücke verwendet werden, um die Anzahl der Übereinstimmungen in einem Text zu zählen .

2. Anwendungsfall

Lassen Sie uns einen Algorithmus entwickeln, mit dem gezählt werden kann, wie oft eine gültige E-Mail in einer Zeichenfolge angezeigt wird .

Um eine E-Mail-Adresse zu ermitteln, verwenden wir ein einfaches Muster für reguläre Ausdrücke:

([a-z0-9_.-]+)@([a-z0-9_.-]+[a-z])

Beachten Sie, dass dies nur zu Demonstrationszwecken ein triviales Muster ist, da der tatsächliche reguläre Ausdruck für den Abgleich gültiger E-Mail-Adressen recht komplex ist.

Wir benötigen diesen regulären Ausdruck in einem Pattern- Objekt, damit wir ihn verwenden können:

Pattern EMAIL_ADDRESS_PATTERN = Pattern.compile("([a-z0-9_.-]+)@([a-z0-9_.-]+[a-z])");

Wir werden uns zwei Hauptansätze ansehen, von denen einer von der Verwendung von Java 9 oder höher abhängt.

In unserem Beispieltext werden wir versuchen, die drei E-Mails in der Zeichenfolge zu finden:

"You can contact me through [email protected], [email protected], and [email protected]"

3. Zählen von Übereinstimmungen für Java 8 und älter

Lassen Sie uns zunächst sehen, wie die Übereinstimmungen mit Java 8 oder älter gezählt werden.

Eine einfache Möglichkeit , die Spiele zu zählen ist zu iterieren über die Entdeckung Methode der Matcher - Klasse. Diese Methode versucht, die nächste Teilsequenz der Eingabesequenz zu finden, die dem Muster entspricht :

Matcher countEmailMatcher = EMAIL_ADDRESS_PATTERN.matcher(TEXT_CONTAINING_EMAIL_ADDRESSES); int count = 0; while (countEmailMatcher.find()) { count++; }

Mit diesem Ansatz finden wir erwartungsgemäß drei Übereinstimmungen:

assertEquals(3, count);

Beachten Sie, dass der Fund Methode nicht die nicht zurück Matcher nach jedem Spiel gefunden - es beginnt wieder bei dem Charakter nach dem Ende der vorherigen Sequenz angepasst beginnen, so dass er keine E - Mail - Adressen überlappend finden funktionieren würde.

Betrachten wir zum Beispiel dieses Beispiel:

String OVERLAPPING_EMAIL_ADDRESSES = "Try to contact us at [email protected]@baeldung.com, [email protected]"; Matcher countOverlappingEmailsMatcher = EMAIL_ADDRESS_PATTERN.matcher(OVERLAPPING_EMAIL_ADDRESSES); int count = 0; while (countOverlappingEmailsMatcher.find()) { count++; } assertEquals(2, count);

Wenn der Regex versucht, Übereinstimmungen in der angegebenen Zeichenfolge zu finden , findet er zuerst "[email protected]" als Übereinstimmung. Da vor dem @ kein Domain-Teil steht, wird der Marker nicht zurückgesetzt und das zweite "@ baeldung.com" wird ignoriert. Im weiteren Verlauf wird "[E-Mail geschützt]" als zweites Spiel betrachtet:

Wie oben gezeigt, haben wir im überlappenden E-Mail-Beispiel nur zwei Übereinstimmungen.

4. Zählen von Übereinstimmungen für Java 9 und höher

Wenn wir jedoch eine neuere Version von Java zur Verfügung haben, können wir die Verwendung Ergebnisse Methode der Matcher - Klasse. Diese in Java 9 hinzugefügte Methode gibt einen sequentiellen Strom von Übereinstimmungsergebnissen zurück, sodass wir die Übereinstimmungen einfacher zählen können:

long count = countEmailMatcher.results() .count(); assertEquals(3, count);

Wie wir bei find gesehen haben , wird der Matcher während der Verarbeitung des Streams aus der Ergebnismethode nicht zurückgesetzt . In ähnlicher Weise würde die Ergebnismethode auch nicht funktionieren, um Übereinstimmungen zu finden, die sich überlappen.

5. Schlussfolgerung

In diesem kurzen Artikel haben wir gelernt, wie man die Übereinstimmungen eines regulären Ausdrucks zählt.

Zuerst haben wir gelernt, wie man die find- Methode mit einer while- Schleife verwendet. Dann haben wir gesehen, wie die neue Java 9-Streaming-Methode es uns ermöglicht, dies mit weniger Code zu tun.

Wie immer sind die Codebeispiele auf GitHub verfügbar.