Vereinfachen Sie häufige Programmieraufgaben mit der Regex-API
In Teil 1 und 2 dieses Artikels wurden Ihnen reguläre Ausdrücke und die Regex-API vorgestellt. Sie haben die Klasse kennengelerntPattern
und sind Beispiele durchgegangen, die reguläre Ausdruckskonstrukte veranschaulichen, vom einfachen Mustervergleich mit Literalzeichenfolgen bis hin zum komplexeren Vergleich mit Bereichen, Grenzvergleichern und Quantifizierern. In diesem und den folgenden Teilen werden wir Themen behandeln, die im ersten Teil nicht behandelt wurden, und wir werden die entsprechenden Methoden der Klassen Pattern
, Matcher
und studieren PatternSyntaxException
. Außerdem lernen Sie zwei Dienstprogramme kennen, die reguläre Ausdrücke verwenden , um häufige Programmierprobleme zu erleichtern. Der erste extrahiert Kommentare aus dem Code zur Dokumentation. Die zweite ist eine Bibliothek mit wiederverwendbarem Code zur Durchführung lexikalischer Analysen – ein wesentlicher Bestandteil von Assemblern, Compilern und ähnlicher Software.
QUELLCODE HERUNTERLADEN
Den gesamten Quellcode (erstellt von Jeff Friesen für JavaWorld) für die Demoanwendungen in diesem Artikel erhalten Sie hier .Erlernen der Regex-API
Pattern
, Matcher
und PatternSyntaxException
sind die drei Klassen, aus denen die Regex-API besteht. Jeder von ihnen bietet Methoden, mit denen Sie reguläre Ausdrücke in Ihrem Code verwenden können.
Methoden der Pattern-Klasse
Eine Instanz einer KlassePattern
ist ein kompilierter regulärer Ausdruck, auch Muster genannt. Reguläre Ausdrücke werden kompiliert, um die Leistung von Mustervergleichsvorgängen zu verbessern. Die folgenden statischen Methoden unterstützen die Kompilierung.
Pattern compile(String regex)
Kompiliert den Inhaltregex
in einer Zwischendarstellung, die in einem neuen gespeichert wirdPattern
. Diese Methode gibt bei Erfolg entweder einen Verweis auf ein Objekt zurück oder löst eine Ausnahme aus,PatternSyntaxException
wenn eine ungültige Syntax für reguläre Ausdrücke erkannt wird. Jedes Objekt der KlasseMatcher
, das von diesem Objekt verwendetPattern
oder von ihm zurückgegeben wird, verwendet seine Standardeinstellungen, z. B. die Suche unter Berücksichtigung der Groß- und Kleinschreibung. BeispielsweisePattern p = Pattern.compile("(?m)^\\.");
erstellt das Code-Snippet ein ObjektPattern
, das eine kompilierte Darstellung eines regulären Ausdrucks speichert, um Zeichenfolgen abzugleichen, die mit einem Punktzeichen beginnen.Pattern compile(String regex, int flags)
löst das gleiche Problem wiePattern compile(String regex)
, berücksichtigt jedoch Folgendesflags
: eine Reihe von Bitkonstanten für Bitflags vom Typ OR. Die KlassePattern
deklariert KonstantenCANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINES
, die mit bitweisem ODER (z. B.CASE_INSENSITIVE | DOTALL
) kombiniert und als Argument übergeben werden könnenflags
.
Mit Ausnahme von
CANON_EQ, LITERAL и UNICODE_CHARACTER_CLASS
stellen diese Konstanten eine Alternative zu den in Teil 1 gezeigten verschachtelten Flag-Ausdrücken dar. Wenn eine andere Flag-Konstante als die in der Klasse definierten angetroffen wird Pattern
, löst die Methode Pattern compile(String regex, int flags)
eine Ausnahme aus java.lang.IllegalArgumentException
. Entspricht beispielsweise Pattern p = Pattern.compile("^\\.", Pattern.MULTILINE);
dem vorherigen Beispiel, wobei die Konstante Pattern.MULTILINE
und der verschachtelte Flag-Ausdruck (?m)
dasselbe bewirken.
Pattern
zusammen mit den verwendeten Flags zu erhalten. Dazu können Sie folgende Methoden aufrufen:
String pattern()
gibt die ursprüngliche Zeichenfolge des regulären Ausdrucks zurück, kompiliert in einePattern
.int flags()
gibt die Flags des Objekts zurückPattern
.
Pattern
wird es normalerweise verwendet, um das Objekt abzurufen Matcher
und Mustervergleichsvorgänge durchzuführen. Die Methode Matcher matcher(Charsequence input)
erstellt ein Objekt Matcher
, das Text input
nach einer Übereinstimmung mit einem Objektmuster durchsucht Pattern
. Beim Aufruf wird eine Referenz auf dieses Objekt zurückgegeben Matcher
. Beispielsweise gibt der Befehl für das Objekt Matcher m = p.matcher(args[1]);
zurück , auf das die Variable verweist . Matcher
Pattern
p
Einmalige Suche |
---|
static boolean matches(String regex, CharSequence input) Mit der Klassenmethode können Sie sich das Erstellen von Objekten und die einmalige Suche mithilfe einer Vorlage Pattern sparen . Diese Methode gibt true zurück, wenn das Muster übereinstimmt , andernfalls gibt sie false zurück. Wenn der reguläre Ausdruck einen Syntaxfehler enthält, löst die Methode eine Ausnahme aus . Beispielsweise gibt prints aus , um zu bestätigen, dass die Phrase nur Leerzeichen und Kleinbuchstaben enthält. Pattern Matcher input regex PatternSyntaxException System.out.println(Pattern.matches("[a-z[\\s]]*", "all lowercase letters and whitespace only")); true all lowercase letters and whitespace only |
Text aufteilen
Die meisten Entwickler haben mindestens einmal Code geschrieben, um Eingabetext in seine Bestandteile zu zerlegen, beispielsweise um ein textbasiertes Mitarbeiterkonto in eine Reihe von Feldern umzuwandeln. Die KlassePattern
bietet die Möglichkeit, diese mühsame Aufgabe mithilfe von zwei Textaufteilungsmethoden bequemer zu lösen:
-
Die Methode
String[] split(CharSequence text, int limit)
teilttext
entsprechend den gefundenen Übereinstimmungen mit dem Objektmuster aufPattern
und gibt die Ergebnisse in einem Array zurück. Jedes Array-Element gibt eine Textsequenz an, die von der nächsten Sequenz durch ein musterübereinstimmendes Textfragment (oder Textende) getrennt ist. Die Elemente des Arrays befinden sich in derselben Reihenfolge, in der sie in erscheinentext
.Bei dieser Methode hängt die Anzahl der Array-Elemente vom Parameter ab
limit
, der auch die Anzahl der zu findenden Übereinstimmungen steuert.- Ein positiver Wert sucht nach nicht mehr als
limit-1
Übereinstimmungen und die Länge des Arrays beträgt nicht mehr alslimit
Elemente. - Wenn der Wert negativ ist, werden alle möglichen Übereinstimmungen durchsucht und die Länge des Arrays kann beliebig sein.
- Wenn der Wert Null ist, werden alle möglichen Übereinstimmungen durchsucht, die Länge des Arrays kann beliebig sein und leere Zeilen am Ende werden verworfen.
- Ein positiver Wert sucht nach nicht mehr als
- Die Methode
String[] split(CharSequence text)
ruft die vorherige Methode mit 0 als Grenzargument auf und gibt das Ergebnis ihres Aufrufs zurück.
split(CharSequence text)
zur Lösung des Problems der Aufteilung eines Mitarbeiterkontos in separate Felder für Name, Alter, Postanschrift und Gehalt:
Pattern p = Pattern.compile(",\\s");
String[] fields = p.split("John Doe, 47, Hillsboro Road, 32000");
for (int i = 0; i < fields.length; i++)
System.out.println(fields[i]);
Der obige Code beschreibt einen regulären Ausdruck zum Suchen eines Kommazeichens, direkt gefolgt von einem einzelnen Leerzeichen. Hier sind die Ergebnisse seiner Ausführung:
John Doe
47
Hillsboro Road
32000
Vorlagenprädikate und die Streams-API
In Java 8Pattern
erschien eine Methode in der Klasse . Diese Methode erstellt ein Prädikat (eine Funktion mit einem booleschen Wert), das zum Abgleichen des Musters verwendet wird. Die Verwendung dieser Methode wird im folgenden Codeausschnitt gezeigt: Predicate
asPredicate()
List progLangs = Arrays.asList("apl", "basic", "c", "c++", "c#", "cobol", "java", "javascript", "perl", "python", "scala");
Pattern p = Pattern.compile("^c");
progLangs.stream().filter(p.asPredicate()).forEach(System.out::println);
Dieser Code erstellt eine Liste von Programmiersprachennamen und kompiliert dann ein Muster, um alle Namen zu finden, die mit dem Buchstaben beginnen c
. Die letzte Codezeile oben implementiert den Empfang eines seriellen Datenstroms mit dieser Liste als Quelle. Mithilfe einer booleschen Funktion wird ein Filter eingerichtet, asPredicate()
der „true“ zurückgibt, wenn der Name mit einem Buchstaben beginnt c
, den Stream durchläuft und übereinstimmende Namen auf der Standardausgabe ausgibt. Diese letzte Zeile entspricht der folgenden regulären Schleife, die aus der RegexDemo-Anwendung aus Teil 1 bekannt ist:
for (String progLang: progLangs)
if (p.matcher(progLang).find())
System.out.println(progLang);
Methoden der Matcher-Klasse
Eine Instanz der KlasseMatcher
beschreibt einen Mechanismus zum Durchführen von Mustervergleichsoperationen für eine Zeichenfolge durch Interpretation des kompilierten regulären Ausdrucks der Klasse Pattern
. Objekte der Klasse Matcher
unterstützen verschiedene Arten von Mustersuchoperationen:
-
Die Methode
boolean find()
durchsucht den Eingabetext nach der nächsten Übereinstimmung. Diese Methode beginnt mit dem Scannen entweder am Anfang des angegebenen Texts oder beim ersten Zeichen nach der vorherigen Übereinstimmung. Die zweite Option ist nur möglich, wenn der vorherige Aufruf dieser Methode „true“ zurückgegeben hat und der Resolver nicht zurückgesetzt wurde. In jedem Fall wird bei erfolgreicher Suche der boolesche Wert true zurückgegeben. Ein Beispiel für diese Methode finden Sie inRegexDemo
Teil 1. -
Die Methode
boolean find(int start)
setzt den Matcher zurück und durchsucht den Text nach der nächsten Übereinstimmung. Die Betrachtung beginnt an der durch den Parameter angegebenen Positionstart
. Bei erfolgreicher Suche wird der boolesche Wert true zurückgegeben. Scannt beispielsweisem.find(1);
den Text ab Position1
(Position 0 wird ignoriert). Wenn der Parameterstart
einen negativen Wert oder einen Wert enthält, der größer als die Textlänge des Matchers ist, löst die Methode eine Ausnahme ausjava.lang.IndexOutOfBoundsException
. -
Die Methode
boolean matches()
versucht, den gesamten Text einem Muster zuzuordnen. Es gibt den booleschen Wert „true“ zurück, wenn der gesamte Text mit dem Muster übereinstimmt. Beispielsweise wird der CodePattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.matches());
ausgegeben ,false
weil das Zeichen!
kein Wortzeichen ist. -
Die Methode
boolean lookingAt()
versucht, den angegebenen Text mit dem Muster abzugleichen. Diese Methode gibt true zurück, wenn ein Teil des Textes mit dem Muster übereinstimmt. Im Gegensatz zur Methodematches();
muss nicht der gesamte Text mit dem Muster übereinstimmen. Es wird beispielsweisePattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.lookingAt());
ausgegebentrue
, da der Anfang des Textesabc!
nur aus wortbildenden Zeichen besteht.
Pattern
Klassenobjekte Matcher
Statusinformationen bei. Manchmal müssen Sie den Matcher möglicherweise zurücksetzen, um diese Informationen zu löschen, nachdem die Mustersuche abgeschlossen ist. Zum Zurücksetzen des Resolvers stehen folgende Methoden zur Verfügung:
-
Die Methode
Matcher reset()
setzt den Status des Matchers zurück, einschließlich der Position, die am Ende angehängt werden soll (auf 0 zurücksetzen). Der nächste Mustersuchvorgang beginnt am Anfang des Matcher-Textes. Gibt einen Verweis auf das aktuelle Objekt zurückMatcher
. Setzt beispielsweisem.reset();
den Resolver zurück, auf den verwiesen wirdm
. -
Die Methode
Matcher reset(CharSequence text)
setzt den Resolver-Status zurück und setzt den neuen Resolver-Text auftext
. Der nächste Mustersuchvorgang beginnt am Anfang des neuen Matcher-Textes. Gibt einen Verweis auf das aktuelle Objekt zurückMatcher
. Setzt beispielsweisem.reset("new text");
den referenzierten Resolver zurückm
und legt den neuen Resolvertext auf fest"new text"
.
Text am Ende hinzufügen
Die Position des Matchers, der an das Ende angehängt werden soll, gibt den Anfang des Matcher-Textes an, der an das Ende des Objekts vom Typ angehängt wirdjava.lang.StringBuffer
. Die folgenden Methoden verwenden diese Position:
-
Die Methode
Matcher appendReplacement(StringBuffer sb, String replacement)
liest die Matcher-Textzeichen und hängt sie an das Ende des Objekts, auf dasStringBuffer
das Argument verweistsb
. Diese Methode stoppt das Lesen beim letzten Zeichen vor der vorherigen Musterübereinstimmung. Als nächstes hängt die Methode die Zeichen aus dem Objekt des Typs,String
auf den das Argument verweist,replacement
an das Ende des Objekts anStringBuffer
(die Zeichenfolgereplacement
kann Verweise auf Textsequenzen enthalten, die während der vorherigen Suche erfasst wurden; diese werden anhand der($)
erfassten Zeichen und Gruppennummern angegeben). Schließlich legt die Methode den Wert der Matcher-Position fest, der an die Position des letzten übereinstimmenden Zeichens plus eins angehängt werden soll, und gibt dann einen Verweis auf den aktuellen Matcher zurück. -
Die Methode
StringBuffer appendTail(StringBuffer sb)
fügt den gesamten Text zu einem Objekt hinzuStringBuffer
und gibt einen Verweis auf dieses Objekt zurück. Rufen Sie nach dem letzten MethodenaufrufappendReplacement(StringBuffer sb, String replacement)
die Methode auf,appendTail(StringBuffer sb)
um den verbleibenden Text in das Objekt zu kopierenStringBuffer
.
Die Methode Matcher appendReplacement(StringBuffer sb, String replacement)
löst eine Ausnahme aus java.lang.IllegalStateException
, wenn der Matcher noch keine Übereinstimmung gefunden hat oder ein vorheriger Suchversuch fehlgeschlagen ist. Es wird eine Ausnahme ausgelöst IndexOutOfBoundsException
, wenn die Zeile replacement
eine Capture-Gruppe angibt, die nicht im Muster enthalten ist.
Erfasste Gruppen |
---|
Wie Sie sich aus Teil 1 erinnern, ist eine Erfassungsgruppe eine Folge von Zeichen, die in () Metazeichen in Klammern ( ) eingeschlossen sind. Der Zweck dieses Konstrukts besteht darin, die gefundenen Zeichen zur späteren Wiederverwendung beim Mustervergleich zu speichern. Bei der Mustersuche werden alle Zeichen der erfassten Gruppe als Ganzes betrachtet. |
appendReplacement(StringBuffer sb, String replacement)
und auf appendTail(StringBuffer sb
, um alle Vorkommen der Zeichenfolge im Quelltext cat
durch zu ersetzen caterpillar
:
Pattern p = Pattern.compile("(cat)");
Matcher m = p.matcher("one cat, two cats, or three cats on a fence");
StringBuffer sb = new StringBuffer();
while (m.find())
m.appendReplacement(sb, "$1erpillar");
m.appendTail(sb);
System.out.println(sb);
Durch die Verwendung einer erfassten Gruppe und eines Verweises darauf im Ersetzungstext wird das Programm angewiesen, erpillar
nach jedem Vorkommen von einzufügen cat
. Das Ergebnis der Ausführung dieses Codes sieht folgendermaßen aus: one caterpillar, two caterpillars, or three caterpillars on a fence
Text ersetzen
Die KlasseMatcher
stellt uns zwei Methoden zur Textersetzung zur Verfügung, die die ergänzen appendReplacement(StringBuffer sb, String replacement)
. Mit diesen Methoden können Sie entweder das erste Vorkommen von [ersetzter Text] oder alle Vorkommen ersetzen:
-
Die Methode
String replaceFirst(String replacement)
setzt den Matcher zurück, erstellt ein neues ObjektString
, kopiert alle Zeichen des Matcher-Textes (bis zum ersten Treffer) in diese Zeichenfolge, hängt die Zeichen von bis zum Ende anreplacement
, kopiert die verbleibenden Zeichen in die Zeichenfolge und gibt eine zurück ObjektString
(die Zeichenfolgereplacement
kann Verweise auf die bei der vorherigen Suche erfassten Textsequenzen unter Verwendung von Dollarsymbolen und erfassten Gruppennummern enthalten). -
Die Methode
String replaceAll(String replacement)
funktioniert ähnlich wie die MethodeString replaceFirst(String replacement)
, ersetzt jedochreplacement
alle gefundenen Übereinstimmungen durch Zeichen aus der Zeichenfolge.
\s+
sucht nach einem oder mehreren Leerzeichen im Eingabetext. Im Folgenden verwenden wir diesen regulären Ausdruck und rufen eine Methode replaceAll(String replacement)
zum Entfernen doppelter Leerzeichen auf:
Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher("Удаляем \t\t лишние пробелы. ");
System.out.println(m.replaceAll(" "));
Hier sind die Ergebnisse: Удаляем лишние пробелы.
Reguläre Ausdrücke in Java, Teil 4 Reguläre Ausdrücke in Java, Teil 5
GO TO FULL VERSION