Java Regex Zeichenklassen
Vordefinierte und benutzerdefinierte Zeichenklassen in Java Regex — \d, \w, \s, Bereiche, Negation und Schnittmengen.
Eine Zeichenklasse ist der Teil eines regulären Ausdrucks, der ein Zeichen aus einer Menge erlaubter Zeichen abgleicht. Wenn Sie \d, [aeiou] oder [^0-9] schreiben, verwenden Sie eine Zeichenklasse. Sie sind der kleinste Baustein fast jedes nützlichen Musters, und Javas java.util.regex-Engine bietet drei Arten: vorgefertigte Kürzel wie \d, benutzerdefinierte Mengen in [...] und Unicode-fähige benannte Klassen wie \p{Lower}. Wer diese beherrscht, dem fällt der Rest von Regex leicht.
Dieses Kapitel behandelt alle drei Arten — benutzerdefinierte Klassen mit Bereichen und Negation, die vordefinierten Kürzel, Mengenoperationen (Vereinigung, Schnittmenge, Subtraktion) sowie benannte Unicode/POSIX-Klassen — und fasst sie in einem ausführbaren Programm zusammen. Wenn Sie neu in Java Regex sind, lesen Sie zuerst die Regex-Einführung und die Regex-Syntax.
Benutzerdefinierte Klassen: Klammern, Bereiche und Negation
Die eckige-Klammer-Klasse [...] gleicht jedes einzelne Zeichen ab, das darin aufgeführt ist. Listen Sie die Zeichen einzeln auf oder verwenden Sie einen Bindestrich für einen Bereich. Setzen Sie ^ direkt nach der öffnenden Klammer, um die Menge zu negieren — es wird jedes Zeichen abgeglichen, das nicht aufgeführt ist.
"[abc]" // matches one 'a', 'b', or 'c'
"[a-z]" // any one lowercase letter (a range)
"[A-Za-z0-9]"// any letter or digit (three ranges in one class)
"[^aeiou]" // any single character that is NOT a vowelInnerhalb einer Klasse verlieren die meisten Metazeichen ihre besondere Bedeutung, sodass Sie sie selten escapen müssen. Ausnahmen sind ], ^, - und \ — escapen Sie diese, oder positionieren Sie sie so, dass sie nicht fehlgedeutet werden können (ein - am Anfang oder Ende ist ein wörtlicher Bindestrich, kein Bereich).
java.util.regex.Pattern p = java.util.regex.Pattern.compile("[-+0-9]");
System.out.println(p.matcher("-").find()); // true: leading - is literal
System.out.println(p.matcher("*").find()); // falseVordefinierte Klassen: die Kürzel
Java liefert Kürzel für die Mengen, die Sie ständig benötigen. Jede Kleinbuchstaben-Form hat ein Komplement in Großbuchstaben, das alles abgleicht, was die Kleinbuchstaben-Form nicht abgleicht.
| Kürzel | Gleicht ab | Äquivalente Klasse |
|---|---|---|
. | jedes Zeichen außer Zeilenterminatoren | — |
\d | eine Ziffer | [0-9] |
\D | eine Nicht-Ziffer | [^0-9] |
\w | ein Wortzeichen | [a-zA-Z_0-9] |
\W | ein Nicht-Wortzeichen | [^a-zA-Z_0-9] |
\s | ein Leerzeichen | [ \t\n\x0B\f\r] |
\S | ein Nicht-Leerzeichen | [^\s] |
\d in einem String-Literal als "\\d" geschrieben und \w wird zu "\\w". Den zweiten Backslash zu vergessen ist der häufigste Java-Regex-Fehler — "\d" kompiliert nicht einmal.String digits = "\\d+"; // regex is \d+ (one or more digits)
String word = "\\w+"; // regex is \w+
"abc123".replaceAll("\\d", "#"); // "abc###"Negation vs. Schnittmenge vs. Vereinigung
Eine Klammer-Klasse ist standardmäßig eine Vereinigung — [abcxyz] gleicht jedes der sechs Zeichen ab. Java fügt zwei Mengenoperatoren innerhalb von Klassen hinzu. Der &&-Operator bildet eine Schnittmenge (nur Zeichen, die in beiden Mengen vorkommen), und das Verschachteln einer Klasse in eine andere erlaubt die Subtraktion.
| Konstrukt | Bedeutung |
|---|---|
[a-d[m-p]] | Vereinigung: a–d oder m–p |
[a-z&&[aeiou]] | Schnittmenge: Kleinbuchstaben, die Vokale sind |
[a-z&&[^aeiou]] | Subtraktion: Kleinbuchstaben, die keine Vokale sind (Konsonanten) |
"[a-z&&[^aeiou]]" // all lowercase consonants
"[\\p{L}&&[^\\p{Lu}]]" // any letter that is not uppercaseNegation mit ^ kehrt eine ganze Klasse um; Schnittmenge mit && schränkt sie ein. Das richtige Werkzeug zu wählen hält Muster lesbar, anstatt Alternationen aufzuhäufen.
Unicode- und POSIX-benannte Klassen
Für alles jenseits von ASCII verwenden Sie die \p{...}-Familie. Diese benannten Klassen kennen Unicode-Kategorien und POSIX-Gruppen, und \P{...} ist die negierte Form. Sie sind unverzichtbar, sobald Ihre Eingabe akzentuierte Buchstaben, nicht-lateinische Schriften enthält oder Sie einfach aussagekräftige Namen bevorzugen.
| Klasse | Gleicht ab |
|---|---|
\p{Lower} | ein ASCII-Kleinbuchstabe ([a-z]) |
\p{Punct} | ein Interpunktionszeichen |
\p{Alnum} | ein ASCII-Buchstabe oder eine Ziffer |
\p{L} | ein beliebiger Unicode-Buchstabe (mit UNICODE_CHARACTER_CLASS) |
\p{IsDigit} | eine Unicode-Ziffer |
// Make \w, \d, \s honor full Unicode, not just ASCII:
java.util.regex.Pattern uni =
java.util.regex.Pattern.compile("\\w+", java.util.regex.Pattern.UNICODE_CHARACTER_CLASS);
System.out.println(uni.matcher("café").results().count()); // 1: "café" is one wordEin ausgearbeitetes Beispiel: jede Klassenart an einem String
Dieses Programm erstellt einen kleinen Helfer, count, der angibt, wie viele Zeichen eines Beispiel-Strings eine einstellige Klasse abgleicht. Denselben String durch Ziffern-, Wort-, Leerzeichen-, Bereichs-, Negations-, Schnittmengen-, Punkt- und POSIX-Klassen zu führen macht die Beziehungen zwischen ihnen konkret — und zeigt eine Klasse bei echter Arbeit innerhalb eines größeren Musters.
Was der Durchlauf zeigt:
\dund[0-9]melden beide 13 für diesen String — sie sind für ASCII-Eingaben exakt gleichwertig. Eine vordefinierte Klasse ist nur ein eingebauter Name für eine Menge, die man auch selbst ausschreiben könnte; verwenden Sie also das Kürzel für bessere Lesbarkeit.\Dund[^0-9]melden beide 30, das Komplement der 13 Ziffern in einem 43-Zeichen-String (13 + 30 = 43). Ein Großbuchstaben-Kürzel und eine negierte Klammer-Klasse sind zwei Schreibweisen desselben Komplements.[a-z&&[aeiou]]meldet 3 — nur die Kleinbuchstaben-Vokale, nämlich dasevon Order, dasovon cost und dasivon ship-by. Das führendeOvon Order ist ein Großbuchstabe, sodass die Schnittmenge es ausschließt. Der Punkt:&&schränkt eine Klasse auf die Zeichen ein, die in beiden Mengen vorkommen, anstatt sie zu vereinigen; daher kommen Großbuchstaben-Vokale nie in Frage.- Der Punkt gleicht 43 Zeichen ab, jedes einschließlich Leerzeichen und Interpunktion, weil dieser einzeilige String keinen Zeilenterminator enthält, an dem
.stoppen würde. Der Punkt ist die breiteste Klasse von allen, weshalb Sie ihn normalerweise durch eine engere ersetzen. - Das Muster
[A-Z]\dfandA7: Zeichenklassen dienen nicht nur zum Zählen — kombiniert in einer Sequenz validieren sie Struktur, hier ein Buchstabe unmittelbar gefolgt von einer Ziffer.\p{Punct}fand separat 9 Interpunktionszeichen und zeigt damit, dass benannte POSIX-Klassen neben den Kürzeln funktionieren.
Übungsaufgaben
Wie geht es weiter
Eine Zeichenklasse gleicht ein Zeichen ab; der nächste Schritt ist zu steuern, wie viele davon abgeglichen werden und was mit dem Ergebnis geschieht:
- Regex-Quantifizierer — fügen Sie
+,*,?und{n,m}hinzu, damit eine Klasse eine Folge von Zeichen abgleicht. - Capture-Gruppen — schließen Sie eine Klasse in
(...)ein, um eine abgeglichene Teilzeichenkette zu extrahieren. - Pattern und Matcher — die API aus jedem obigen Beispiel, vertieft behandelt.
- Regex-Flags —
CASE_INSENSITIVE,UNICODE_CHARACTER_CLASSund weitere Optionen, die das Verhalten von Klassen ändern.