Wir machen Sie auf die Übersetzung einer kurzen Anleitung zu regulären Ausdrücken in der Java-Sprache aufmerksam, die Jeff Friesen für die
JavaWorld- Website geschrieben hat . Zur besseren Lesbarkeit haben wir den Artikel in mehrere Teile gegliedert.
Verwendung der Regular Expression API in Java-Programmen zum Erkennen und Beschreiben von Mustern
Die Zeichen- und verschiedenen String-Datentypen von Java bieten eine Low-Level-Unterstützung für den Mustervergleich, ihre Verwendung für diesen Zweck erhöht jedoch in der Regel die Komplexität des Codes erheblich. Einfacherer und leistungsfähigerer Code wird durch die Verwendung der Regex-API („Regular Expression API“) erhalten. Dieses Tutorial hilft Ihnen beim Einstieg in reguläre Ausdrücke und die Regex-API. Wir besprechen zunächst die drei interessantesten Klassen im Paket im Allgemeinen
java.util.regex
, werfen dann einen Blick in die Klasse
Pattern
und erkunden ihre ausgefeilten Mustervergleichskonstrukte.
Aufmerksamkeit: Sie können den Quellcode (erstellt von Jeff Friesen für die JavaWorld-Site) der Demoanwendung aus diesem Artikel
hier herunterladen .
Was sind reguläre Ausdrücke?
Ein regulärer Ausdruck (regular expression/regex/regexp) ist eine Zeichenfolge, die ein Muster darstellt, das einen bestimmten Satz von Zeichenfolgen beschreibt. Das Muster bestimmt, welche Zeilen zur Menge gehören. Das Muster besteht aus Literalen und Metazeichen – Zeichen mit einer besonderen Bedeutung und nicht mit einer wörtlichen Bedeutung. Beim Mustervergleich handelt es sich um eine Textsuche, um Übereinstimmungen zu finden, d. h. Zeichenfolgen, die mit einem regulären Ausdrucksmuster übereinstimmen. Java unterstützt den Mustervergleich über seine Regex-API. Diese API besteht aus drei Klassen:
Pattern
,
Matcher
und
PatternSyntaxException
, die sich im Paket befinden
java.util.regex
:
- Klassenobjekte
Pattern
, auch Vorlagen genannt, sind kompilierte reguläre Ausdrücke.
- Klassenobjekte
Matcher
oder Matcher sind Musterinterpretationsmechanismen zum Finden von Übereinstimmungen in Zeichenfolgen (Objekte, deren Klassen eine Schnittstelle implementieren java.lang.CharSequence
und als Textquellen dienen).
- Klassenobjekte
PatternSyntaxException
werden verwendet, um ungültige reguläre Ausdrucksmuster zu beschreiben.
Java bietet auch Unterstützung für den Mustervergleich durch verschiedene Methoden der
java.lang.String
. Beispielsweise gibt die Funktion nur dann
boolean matches (String regex)
ein Ergebnis zurück
true
, wenn die aufrufende Zeichenfolge genau mit dem regulären Ausdruck übereinstimmt
regex
.
Bequeme Methoden |
matches() und andere an regulären Ausdrücken orientierte praktische Methoden der Klasse String werden auf ähnliche Weise wie die Regex-API unter der Haube implementiert. |
RegexDemo
Ich habe eine Anwendung erstellt,
RegexDemo
um reguläre Java-Ausdrücke und verschiedene Methoden von
Pattern
,
Matcher
und zu demonstrieren
PatternSyntaxException
. Unten finden Sie den Quellcode für diese Demoanwendung. Listing 1. Demonstration regulärer Ausdrücke
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class RegexDemo
{
public static void main(String[] args)
{
if (args.length != 2)
{
System.err.println("usage: java RegexDemo regex input");
return;
}
args[1] = args[1].replaceAll("\\\\n", "\n");
try
{
System.out.println("regex = " + args[0]);
System.out.println("input = " + args[1]);
Pattern p = Pattern.compile(args[0]);
Matcher m = p.matcher(args[1]);
while (m.find())
System.out.println("Found [" + m.group() + "] starting at "
+ m.start() + " and ending at " + (m.end() - 1));
}
catch (PatternSyntaxException pse)
{
System.err.println("Неправильное регулярное выражение: " + pse.getMessage());
System.err.println("Описание: " + pse.getDescription());
System.err.println("Позиция: " + pse.getIndex());
System.err.println("Неправильный шаблон: " + pse.getPattern());
}
}
}
main
Das erste, was eine Klassenmethode tut,
RegexDemo
ist, ihre Befehlszeile zu überprüfen. Es sind zwei Argumente erforderlich: Das erste ist ein regulärer Ausdruck und das zweite ist der Eingabetext, in dem nach dem regulären Ausdruck gesucht wird. Möglicherweise müssen Sie im Eingabetext ein Zeilenumbruchzeichen verwenden
(\n)
.
\
Dies kann nur durch die Angabe des Zeichens gefolgt vom Zeichen erfolgen
n
. Die Funktion
main()
wandelt diese Zeichenfolge in den Unicode-Wert 10 um.
Der Großteil des Codes
RegexDemo
ist in der enthalten
try-catch
. Der Block
try
gibt zunächst den angegebenen regulären Ausdruck und den Eingabetext aus und erstellt dann ein Objekt
Pattern
, das den kompilierten regulären Ausdruck speichert (reguläre Ausdrücke werden kompiliert, um die Leistung des Mustervergleichs zu verbessern). Ein Matcher wird aus dem Objekt extrahiert
Pattern
und verwendet, um iterativ nach Übereinstimmungen zu suchen, bis alle gefunden sind. Der Block
catch
ruft mehrere Klassenmethoden auf
PatternSyntaxException
, um nützliche Informationen über die Ausnahme abzurufen. Diese Informationen werden sequentiell an den Ausgabestream ausgegeben. Es besteht noch keine Notwendigkeit, die Details der Funktionsweise des Codes zu kennen: Sie werden klar, wenn wir die API im zweiten Teil des Artikels untersuchen. Sie müssen jedoch Listing 1 kompilieren. Nehmen Sie den Code aus Listing 1 und geben Sie dann zum Kompilieren den folgenden Befehl an der Eingabeaufforderung ein
RegexDemo
:
javac RegexDemo.java
Die Pattern-Klasse und ihre Konstrukte
Die Klasse
Pattern
, die erste von drei Klassen, aus denen die Regex-API besteht, ist eine kompilierte Darstellung eines regulären Ausdrucks. In der Klassen-SDK-Dokumentation
Pattern
werden verschiedene reguläre Ausdruckskonstrukte beschrieben. Wenn Sie reguläre Ausdrücke jedoch nicht aktiv verwenden, können Teile dieser Dokumentation verwirrend sein. Was sind Quantoren und was ist der Unterschied zwischen gierigen, widerstrebenden und besitzergreifenden Quantoren? Was sind Zeichenklassen, Boundary-Matcher, Rückverweise und eingebettete Flag-Ausdrücke? Diese und weitere Fragen werde ich in den folgenden Abschnitten beantworten.
Literale Zeichenfolgen
Das einfachste Konstrukt eines regulären Ausdrucks ist eine Literalzeichenfolge. Damit der Mustervergleich erfolgreich ist, muss ein Teil des Eingabetextes mit dem Muster dieses Konstrukts übereinstimmen. Betrachten Sie das folgende Beispiel:
java RegexDemo apple applet
In diesem Beispiel versuchen wir, eine Übereinstimmung für ein Muster
apple
im Eingabetext zu finden
applet
. Das folgende Ergebnis zeigt die gefundene Übereinstimmung:
regex = apple
input = applet
Found [apple] starting at 0 and ending at 4
In der Ausgabe sehen wir den regulären Ausdruck und den Eingabetext sowie einen Hinweis auf eine erfolgreiche Erkennung
apple
im Applet. Darüber hinaus werden die Start- und Endpositionen dieses Spiels angegeben:
0
bzw.
4
. Die Startposition gibt die erste Stelle im Text an, an der eine Übereinstimmung gefunden wurde, und die Endposition gibt den letzten Punkt der Übereinstimmung an. Nehmen wir nun an, wir hätten die folgende Befehlszeile eingegeben:
java RegexDemo apple crabapple
Dieses Mal erhalten wir das folgende Ergebnis, mit unterschiedlichen Start- und Endpositionen:
regex = apple
input = crabapple
Found [apple] starting at 4 and ending at 8
Andernfalls werden mit und
applet
als regulärem Ausdruck
apple
– dem Eingabetext – keine Übereinstimmungen gefunden. Der gesamte reguläre Ausdruck muss übereinstimmen, aber in diesem Fall enthält der Eingabetext kein
t
after
apple
.
Metazeichen
Interessantere reguläre Ausdruckskonstrukte kombinieren Literalzeichen mit Metazeichen. In einem regulären Ausdruck bedeutet
a.b
das Punkt-Metazeichen beispielsweise jedes Zeichen zwischen und b. Betrachten Sie das folgende Beispiel: In diesem Beispiel wird sowohl ein regulärer Ausdruck als auch ein Eingabetext verwendet. durchsucht den Text nach Übereinstimmungen, die mit einem beliebigen Zeichen beginnen und mit enden. Die Ergebnisse seiner Ausführung sind wie folgt:
(.)
a
java RegexDemo .ox "The quick brown fox jumps over the lazy ox."
.ox
The quick brown fox jumps over the lazy ox.
RegexDemo
ox.
regex = .ox
input = The quick brown fox jumps over the lazy ox.
Found [fox] starting at 16 and ending at 18
Found [ ox] starting at 39 and ending at 41
In der Ausgabe sehen wir zwei Übereinstimmungen:
fox
und
ox
(mit einem Leerzeichen davor). Das Metazeichen
.
entspricht
f
im ersten Fall einem Zeichen und im zweiten Fall einem Leerzeichen.
.ox
Was passiert, wenn Sie es durch ein Metazeichen ersetzen
.
? Das ist das, was wir als Ergebnis der folgenden Befehlszeile erhalten:
java RegexDemo . "The quick brown fox jumps over the lazy ox."
Da das Punkt-Metazeichen mit jedem Zeichen übereinstimmt,
RegexDemo
werden Übereinstimmungen ausgegeben, die für alle Zeichen (einschließlich des abschließenden Punktzeichens) des Eingabetextes gefunden wurden:
regex = .
input = The quick brown fox jumps over the lazy ox.
Found [T] starting at 0 and ending at 0
Found [h] starting at 1 and ending at 1
Found [e] starting at 2 and ending at 2
Found [ ] starting at 3 and ending at 3
Found [q] starting at 4 and ending at 4
Found [u] starting at 5 and ending at 5
Found [i] starting at 6 and ending at 6
Found [c] starting at 7 and ending at 7
Found [k] starting at 8 and ending at 8
Found [ ] starting at 9 and ending at 9
Found [b] starting at 10 and ending at 10
Found [r] starting at 11 and ending at 11
Found [o] starting at 12 and ending at 12
Found [w] starting at 13 and ending at 13
Found [n] starting at 14 and ending at 14
Found [ ] starting at 15 and ending at 15
Found [f] starting at 16 and ending at 16
Found [o] starting at 17 and ending at 17
Found [x] starting at 18 and ending at 18
Found [ ] starting at 19 and ending at 19
Found [j] starting at 20 and ending at 20
Found [u] starting at 21 and ending at 21
Found [m] starting at 22 and ending at 22
Found [p] starting at 23 and ending at 23
Found [s] starting at 24 and ending at 24
Found [ ] starting at 25 and ending at 25
Found [o] starting at 26 and ending at 26
Found [v] starting at 27 and ending at 27
Found [e] starting at 28 and ending at 28
Found [r] starting at 29 and ending at 29
Found [ ] starting at 30 and ending at 30
Found [t] starting at 31 and ending at 31
Found [h] starting at 32 and ending at 32
Found [e] starting at 33 and ending at 33
Found [ ] starting at 34 and ending at 34
Found [l] starting at 35 and ending at 35
Found [a] starting at 36 and ending at 36
Found [z] starting at 37 and ending at 37
Found [y] starting at 38 and ending at 38
Found [ ] starting at 39 and ending at 39
Found [o] starting at 40 and ending at 40
Found [x] starting at 41 and ending at 41
Found [.] starting at 42 and ending at 42
Metazeichen zitieren |
Um . ein beliebiges anderes Metazeichen als Literalzeichen in einem regulären Ausdruckskonstrukt anzugeben, müssen Sie es auf eine der folgenden Arten maskieren:
- Stellen Sie ihm einen Backslash voran.
- Platzieren Sie dieses Metazeichen zwischen
\Q und \E (zum Beispiel \Q.\E ).
Denken Sie daran, alle Zeichen zu duplizieren, die im Zeichenfolgenliteral vorkommen, z. B. String regex = "\\."; Backslashes (z. B. \\. oder \\Q.\\E ). Duplizieren Sie nicht die Backslashes, die Teil eines Befehlszeilenarguments sind. |
Charakterklassen
Manchmal müssen Sie die gesuchten Übereinstimmungen auf einen bestimmten Zeichensatz beschränken. Durchsuchen Sie beispielsweise den Text nach den Vokalen
a
,
e
,
i
,
o
und
u
, wobei jedes Vorkommen eines Vokalbuchstabens als Übereinstimmung gewertet wird. Bei der Lösung solcher Probleme helfen uns Zeichenklassen, die Zeichensätze zwischen den Metazeichen eckiger Klammern (
[ ]
) definieren. Die Klasse
Pattern
unterstützt einfache Zeichenklassen, Bereichsklassen, Umkehr-, Vereinigungs-, Schnitt- und Subtraktionsklassen. Wir werden sie uns jetzt alle ansehen.
Einfache Zeichenklassen
Eine einfache Zeichenklasse besteht aus nebeneinander angeordneten Zeichen und entspricht nur diesen Zeichen. Beispielsweise
[abc]
entspricht die Klasse den Zeichen
a
,
b
und
c
. Betrachten Sie das folgende Beispiel:
java RegexDemo [csw] cave
Wie Sie den Ergebnissen entnehmen können, handelt es sich in diesem Beispiel nur um das Zeichen,
c
für das es eine Übereinstimmung gibt in
cave
:
regex = [csw]
input = cave
Found [c] starting at 0 and ending at 0
Invertierte Zeichenklassen
Eine invertierte Zeichenklasse beginnt mit einem Metazeichen
^
und entspricht nur den Zeichen, die nicht darin enthalten sind. Beispielsweise
[^abc]
stimmt die Klasse mit allen Zeichen außer
a
,
b
und überein
c
. Betrachten Sie das folgende Beispiel:
java RegexDemo "[^csw]" cave
Beachten Sie, dass auf meinem Betriebssystem (Windows) doppelte Anführungszeichen erforderlich sind, da die Shell sie
^
als Escape-Zeichen behandelt. Wie Sie sehen, wurden in diesem Beispiel nur die Zeichen
a
,
v
und gefunden
e
, für die es Übereinstimmungen gibt in
cave
:
regex = [^csw]
input = cave
Found [a] starting at 1 and ending at 1
Found [v] starting at 2 and ending at 2
Found [e] starting at 3 and ending at 3
Bereichszeichenklassen
Eine Bereichszeichenklasse besteht aus zwei durch einen Bindestrich (
-
) getrennten Zeichen. Alle Zeichen, beginnend mit dem Zeichen links vom Bindestrich und endend mit dem Zeichen rechts vom Bindestrich, sind Teil des Bereichs. Der Bereich entspricht beispielsweise
[a-z]
allen lateinischen Kleinbuchstaben. Dies entspricht der Definition einer einfachen Klasse
[abcdefghijklmnopqrstuvwxyz]
. Betrachten Sie das folgende Beispiel:
java RegexDemo [a-c] clown
In diesem Beispiel wird nur das Zeichen gefunden,
c
für das es eine Übereinstimmung gibt
clown
:
regex = [a-c]
input = clown
Found [c] starting at 0 and ending at 0
Reguläre Ausdrücke in Java, Teil 2 Reguläre Ausdrücke in Java, Teil 3 Reguläre Ausdrücke in Java, Teil 4 Reguläre Ausdrücke in Java, Teil 5
Was gibt es sonst noch zu lesen: |
|
GO TO FULL VERSION