W3docs

Java Regex-Flags

Reguläre Ausdrücke in Java mit Flags steuern — CASE_INSENSITIVE, MULTILINE, DOTALL, COMMENTS und inline (?i)-Syntax.

Ein Flag ändert die Interpretation eines regulären Ausdrucks, ohne das Muster selbst zu berühren. Derselbe Ausdruck kann Groß-/Kleinschreibung beachten oder nicht, eine Zeichenkette als eine oder als viele Zeilen behandeln und . über Zeilenumbrüche hinweggehen lassen oder davor anhalten — alles durch Flags gesteuert. In Java gibt es dafür zwei Wege: als int-Konstanten, die an Pattern.compile(pattern, flags) übergeben werden, oder als Inline-Schalter im Stil von (?i), die direkt im Muster stehen. Dieses Kapitel behandelt die Flags, die man täglich braucht, und wie man sie kombiniert.

Die zwei Arten, ein Flag zu setzen

Jedes Flag hat eine Konstante in der Pattern-Klasse. Sie wird als zweites Argument an compile übergeben:

Pattern p = Pattern.compile("error", Pattern.CASE_INSENSITIVE);

Dasselbe Verhalten ist innerhalb des Musters als Inline-Modifikator verfügbar, sodass ein einfacher String-Regex seine eigenen Flags ohne zweites Argument tragen kann:

Pattern p = Pattern.compile("(?i)error");          // whole pattern, case-insensitive
Pattern q = Pattern.compile("(?i:error) CODE");    // only the group is case-insensitive

Inline-Flags sind praktisch, wenn das Muster als einfache Zeichenkette weitergegeben wird — in einer Konfigurationsdatei, einer Datenbankspalte oder einer Annotation — wo kein int zusätzlich übergeben werden kann. Die Konstantenform ist klarer, wenn das Flag Teil des eigentlichen Codes ist.

Die Flags, die man tatsächlich verwendet

KonstanteInlineWirkung
CASE_INSENSITIVE(?i)ASCII-Buchstaben ohne Unterscheidung der Groß-/Kleinschreibung abgleichen
MULTILINE(?m)^ und $ treffen an jedem Zeilenrand, nicht nur am Anfang/Ende des Strings
DOTALL(?s). trifft auch Zeilentrenner (s = „single line")
COMMENTS(?x)Nicht-escapte Leerzeichen ignorieren und # als Kommentar behandeln
UNICODE_CASE(?u)CASE_INSENSITIVE auf Unicode-Buchstaben ausdehnen, nicht nur ASCII
UNICODE_CHARACTER_CLASS(?U)\w, \d, \b nach Unicode-Regeln auswerten
LITERALDas gesamte Muster als einfachen Text behandeln, keine Metazeichen

Eine häufige Überraschung: CASE_INSENSITIVE allein faltet nur ASCII. Um akzentuierte oder nicht-lateinische Buchstaben ohne Groß-/Kleinschreibung abzugleichen, muss es mit UNICODE_CASE kombiniert werden.

Groß-/Kleinschreibung ignorieren

Standardmäßig unterscheidet ein regulärer Ausdruck Groß- und Kleinschreibung, sodass error nicht zu ERROR passt. Mit CASE_INSENSITIVE stimmen beide überein:

Pattern.compile("error").matcher("ERROR").find();                      // false
Pattern.compile("error", Pattern.CASE_INSENSITIVE).matcher("ERROR").find(); // true

// For non-ASCII letters, add UNICODE_CASE:
Pattern.compile("é", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE)
       .matcher("É").find();                                           // true

Zeilenverarbeitung: MULTILINE und DOTALL

Diese beiden sind unabhängig und werden oft verwechselt. MULTILINE ändert die Anker ^ und $; DOTALL ändert den Punkt ..

String text = "first line\nsecond line";

// Without MULTILINE, ^ matches only the very start of the input.
Pattern.compile("^second").matcher(text).find();                  // false
// With MULTILINE, ^ matches the start of every line.
Pattern.compile("^second", Pattern.MULTILINE).matcher(text).find(); // true

// Without DOTALL, . will not cross the newline.
Pattern.compile("first.*second").matcher(text).find();            // false
// With DOTALL, . matches the newline too.
Pattern.compile("first.*second", Pattern.DOTALL).matcher(text).find(); // true

MULTILINE eignet sich beim zeilenweisen Durchsuchen mehrzeiliger Log- oder Dokumenttexte, während DOTALL benötigt wird, wenn ein einzelner Treffer mehrere Zeilen überspannen soll (ein HTML-Block, ein mehrzeiliger Datensatz).

Flags kombinieren

Flag-Konstanten sind Bit-Masken und werden daher mit dem bitweisen OR-Operator | kombiniert:

int flags = Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
Pattern p = Pattern.compile("^error.*done$", flags);

Das Inline-Äquivalent stapelt die Buchstaben: (?ims) setzt alle drei. Mit einem Minus lässt sich ein Flag auch innerhalb einer Gruppe deaktivieren: (?-i) schaltet die Groß-/Kleinschreibungsignorierung für den Rest des Musters ab.

Lesbare Muster mit COMMENTS

Das COMMENTS-Flag (Inline (?x)) lässt ein komplexes Muster aufatmen: Nicht-escapte Leerzeichen werden ignoriert, und # beginnt einen Kommentar bis zum Zeilenende. Damit wird ein unlesbarer Einzeiler zu etwas Wartbarem:

Pattern phone = Pattern.compile("""
    \\d{3}   # area code
    -        # separator
    \\d{4}   # line number
    """, Pattern.COMMENTS);
phone.matcher("555-1234").matches();   // true

Da echte Leerzeichen ignoriert werden, kann ein wörtliches Leerzeichen mit \\s, \\ oder einer Zeichenklasse wie [ ] abgeglichen werden.

Ein durchgearbeitetes Beispiel: ein Ausdruck, viele Flags

Dieses Programm führt dieselbe Handvoll Muster mit und ohne Flags aus, damit jeder Flag-Wechsel des Ergebnisses sichtbar wird. Es zählt Treffer ohne Groß-/Kleinschreibung, verankert Zeilen mit MULTILINE, überspannt Zeilenumbrüche mit DOTALL, kombiniert Flags mit | und verwendet sowohl globale als auch auf Gruppen beschränkte Inline-Schalter.

java— editable, runs on the server

Was man aus der Ausgabe mitnehmen kann:

  • CASE_INSENSITIVE fand 2 Vorkommen von error (das großgeschriebene ERROR und das kleingeschriebene error), während das Standard-Muster nur 1 fand — Beweis dafür, dass die Groß-/Kleinschreibungsunterscheidung aktiv ist, bis man das Flag explizit anfordert.
  • MULTILINE ließ ^error:.*$ die mittlere Zeile des Logs treffen und gab error: timeout aus; ohne das Flag würden ^ und $ nur die Enden des gesamten Strings verankern, sodass diese innere Zeile nie passen würde.
  • DOTALL ließ warn.*info über die zwei eingebetteten Zeilenumbrüche hinwegspringen und lieferte true, während dasselbe Muster ohne das Flag false zurückgab, weil . standardmäßig vor einem Zeilentrenner stoppt.
  • Das kombinierte MULTILINE | CASE_INSENSITIVE-Muster traf ^ERROR auf eine Zeile, die tatsächlich mit dem Kleinbuchstaben error: beginnt — true bestätigt, dass beide Flags gleichzeitig durch eine einzige bitweise-OR-Maske angewendet wurden.
  • Das begrenzte (?i:hello) WORLD traf HELLO WORLD (true), aber nicht HELLO world (false): Die (?i:...)-Gruppe faltete die Schreibweise nur für hello und ließ das nachfolgende WORLD streng groß-/kleinschreibungssensitiv — genau die Präzision, die Inline-Scoping bietet.

Verwandte Themen

Übungen

Übung
Sie kompilieren ein Muster mit Pattern.compile('first.*second', Pattern.MULTILINE) und gleichen es gegen den Text 'first line\nsecond line' ab. Warum schlägt der Abgleich fehl, und welches Flag würde das Problem beheben?
Sie kompilieren ein Muster mit Pattern.compile('first.*second', Pattern.MULTILINE) und gleichen es gegen den Text 'first line\nsecond line' ab. Warum schlägt der Abgleich fehl, und welches Flag würde das Problem beheben?
Was this page helpful?