Flag Regex in Java
Modifica il comportamento delle regex Java con i flag — CASE_INSENSITIVE, MULTILINE, DOTALL, COMMENTS e la sintassi inline (?i).
Un flag cambia il modo in cui un'espressione regolare viene interpretata senza modificare il pattern stesso. La stessa espressione può trovare corrispondenze con o senza distinzione tra maiuscole e minuscole, trattare una stringa come una singola riga o come più righe, e lasciare che . attraversi le interruzioni di riga oppure si fermi ad esse — tutto deciso dai flag. In Java puoi impostarli in due modi: come costanti int passate a Pattern.compile(pattern, flags), oppure come switch inline in stile (?i) scritti all'interno del pattern. Questo capitolo tratta i flag che usi quotidianamente e come combinarli.
I due modi per impostare un flag
Ogni flag ha una costante nella classe Pattern. Passala come secondo argomento a compile:
Pattern p = Pattern.compile("error", Pattern.CASE_INSENSITIVE);Lo stesso comportamento è disponibile all'interno del pattern come modificatore inline, così una regex semplice può portare i propri flag senza un secondo argomento:
Pattern p = Pattern.compile("(?i)error"); // whole pattern, case-insensitive
Pattern q = Pattern.compile("(?i:error) CODE"); // only the group is case-insensitiveI flag inline sono utili quando il pattern viene trasportato come stringa semplice — un file di configurazione, una colonna di database, un'annotazione — dove non puoi anche passare un int. La forma con costante è più chiara quando il flag fa parte del tuo codice.
I flag che userai davvero
| Costante | Inline | Effetto |
|---|---|---|
CASE_INSENSITIVE | (?i) | Trova corrispondenze con le lettere ASCII indipendentemente dal caso |
MULTILINE | (?m) | ^ e $ corrispondono a ogni confine di riga, non solo agli estremi della stringa |
DOTALL | (?s) | . corrisponde anche ai terminatori di riga (s = "single line") |
COMMENTS | (?x) | Ignora gli spazi non escapati e tratta # come un commento |
UNICODE_CASE | (?u) | Fa sì che CASE_INSENSITIVE gestisca le lettere Unicode, non solo ASCII |
UNICODE_CHARACTER_CLASS | (?U) | Fa sì che \w, \d, \b seguano le regole Unicode |
LITERAL | — | Tratta l'intero pattern come testo semplice, senza metacaratteri |
Una sorpresa comune: CASE_INSENSITIVE da solo gestisce solo l'ASCII. Per trovare corrispondenze con lettere accentate o non latine senza distinzione tra maiuscole e minuscole, combinalo con UNICODE_CASE.
Insensibilità al caso
Per impostazione predefinita una regex è sensibile al caso, quindi error non corrisponde a ERROR. Aggiungendo CASE_INSENSITIVE entrambi trovano corrispondenza:
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(); // trueGestione delle righe: MULTILINE e DOTALL
Questi due sono indipendenti e spesso confusi. MULTILINE cambia gli ancoraggi ^ e $; DOTALL cambia il punto ..
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(); // trueUsa MULTILINE quando analizzi testo multi-riga di log o documenti riga per riga, e DOTALL quando una singola corrispondenza deve estendersi su più righe (un blocco HTML, un record multi-riga).
Combinare i flag
Le costanti dei flag sono maschere di bit, quindi le combini con l'operatore OR bit a bit |:
int flags = Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
Pattern p = Pattern.compile("^error.*done$", flags);L'equivalente inline impila le lettere: (?ims) imposta tutti e tre. Puoi anche disattivare un flag all'interno di un gruppo con un meno: (?-i) disabilita l'insensibilità al caso per il resto del pattern.
Pattern leggibili con COMMENTS
Il flag COMMENTS (inline (?x)) permette a un pattern complesso di respirare: gli spazi non escapati vengono ignorati e # inizia un commento fino a fine riga. Questo trasforma un'indecifrabile riga unica in qualcosa che puoi mantenere:
Pattern phone = Pattern.compile("""
\\d{3} # area code
- # separator
\\d{4} # line number
""", Pattern.COMMENTS);
phone.matcher("555-1234").matches(); // truePoiché gli spazi reali vengono ignorati, per trovare uno spazio letterale usa \\s, \\ , o una classe di caratteri come [ ].
Un esempio pratico: un'espressione, molti flag
Questo programma esegue la stessa manciata di pattern con e senza flag in modo da poter vedere ogni flag che cambia il risultato. Conta le corrispondenze senza distinzione tra maiuscole e minuscole, ancora le righe con MULTILINE, attraversa le interruzioni di riga con DOTALL, combina i flag con |, e usa sia switch inline globali che con scope.
Cosa ricavare dall'esecuzione:
CASE_INSENSITIVEha trovato 2 occorrenze dierror(laERRORmaiuscola e laerrorminuscola) mentre il pattern predefinito ne ha trovata solo 1 — la prova che la sensibilità al caso è attiva a meno che non si richieda il flag.MULTILINEha fatto corrispondere^error:.*$alla riga centrale del log e ha stampatoerror: timeout; senza il flag,^e$ancorano solo agli estremi dell'intera stringa, quindi quella riga interna non corrisponderebbe mai.DOTALLha permesso awarn.*infodi saltare attraverso le due interruzioni di riga incorporate e trovare corrispondenza (true), mentre lo stesso pattern senza il flag ha restituitofalseperché.si ferma a un terminatore di riga per impostazione predefinita.- Il pattern combinato
MULTILINE | CASE_INSENSITIVEha trovato corrispondenza per^ERRORin una riga che inizia effettivamente conerror:minuscolo —trueconferma che entrambi i flag erano applicati contemporaneamente da una singola maschera OR bit a bit. - Il pattern con scope
(?i:hello) WORLDha trovato corrispondenza conHELLO WORLD(true) ma non conHELLO world(false): il gruppo(?i:...)ha gestito il caso solo perhello, lasciando ilWORLDfinale rigorosamente sensibile al caso — esattamente la precisione che lo scoping inline offre.
Argomenti correlati
- Espressioni Regolari Java — Introduzione — come
PatterneMatchersi integrano. - Pattern e Matcher — le classi che utilizzano i flag sopra descritti.
- Sintassi Regex e Classi di Caratteri — i metacaratteri che i flag modificano.
- Quantificatori e Gruppi — dove i flag inline con scope come
(?i:...)sono più utili.