Ho scritto un'espressione regolare che funziona bene in un determinato programma (grep, sed, awk, perl, python, ruby, ksh, bash, zsh, find, emacs, vi, vim, gedit, ...). Ma quando lo uso in un programma diverso (o su una variante unix diversa), smette di corrispondere. Perché?
Risposta accettata:
Sfortunatamente, per ragioni storiche, strumenti diversi hanno una sintassi delle espressioni regolari leggermente diversa e talvolta alcune implementazioni hanno estensioni che non sono supportate da altri strumenti. Sebbene ci sia un terreno comune, sembra che ogni scrittore di strumenti abbia fatto delle scelte diverse.
La conseguenza è che se si dispone di un'espressione regolare che funziona in uno strumento, potrebbe essere necessario modificarla per funzionare in un altro strumento. Le principali differenze tra gli strumenti comuni sono:
- se gli operatori
+?|(){}
richiedono una barra rovesciata; - quali estensioni sono supportate oltre alle nozioni di base
.[]*^$
e di solito+?|()
In questa risposta, elenco gli standard principali. Controlla la documentazione degli strumenti che stai utilizzando per i dettagli.
Il confronto di Wikipedia sui motori di espressioni regolari ha una tabella che elenca le funzionalità supportate dalle implementazioni comuni.
Espressioni regolari di base (BRE)
Le espressioni regolari di base sono codificate dallo standard POSIX. È la sintassi usata da grep
, sed
e vi
. Questa sintassi fornisce le seguenti caratteristiche:
^
e$
corrisponde solo all'inizio e alla fine di una riga..
corrisponde a qualsiasi carattere (o qualsiasi carattere eccetto una nuova riga).[…]
corrisponde a qualsiasi carattere elencato tra parentesi (set di caratteri). Se il primo carattere dopo la parentesi aperta è un^
, vengono invece abbinati i caratteri non elencati. Per includere un]
, inseriscilo subito dopo l'apertura[
(o dopo[^
se è un insieme negativo). Se-
è compreso tra due caratteri, denota un intervallo; per includere un letterale-
, inseriscilo dove non può essere analizzato come intervallo.- Barra rovesciata prima di qualsiasi di
^$.*[
cita il carattere successivo. *
corrisponde al carattere o alla sottoespressione precedente 0, 1 o più volte.(…)
è un gruppo sintattico, da utilizzare con il*
operatore o backreference eDIGIT
sostituzioni.- Riferimenti precedenti
1
,2
, … abbina il testo esatto corrispondente al gruppo corrispondente, ad es.(fo*)(ba*)1
corrisponde afoobaafoo
ma nonfoobaafo
. Non esiste un modo standard per fare riferimento al 10° gruppo e oltre (il significato standard di10
è il primo gruppo seguito da un).
Anche le seguenti funzionalità sono standard, ma mancano in alcune implementazioni limitate:
{m,n}
corrisponde al carattere o alla sottoespressione precedente tra m a n volte; n o io può essere omesso e{m}
significa esattamente m .- Tra parentesi si possono usare classi di caratteri, ad esempio
[[:alpha:]]
corrisponde a qualsiasi lettera. Le moderne implementazioni delle espressioni tra parentesi) includono anche elementi di confronto come[.ll.]
e classi di equivalenza come[=a=]
.
Le seguenti sono estensioni comuni (specialmente negli strumenti GNU), ma non si trovano in tutte le implementazioni. Consulta il manuale dello strumento che stai utilizzando.
|
in alternativa:foo|bar
corrisponde afoo
obar
.?
(abbreviazione di{0,1}
) e+
(abbreviazione di{1,}
) corrisponde al carattere o alla sottoespressione precedente al massimo 1 volta, o almeno 1 volta rispettivamente.n
corrisponde a una nuova riga,t
corrisponde a una scheda, ecc.w
corrisponde a qualsiasi componente di una parola (abbreviazione di[_[:alnum:]]
ma con variazioni per quanto riguarda la localizzazione) eW
corrisponde a qualsiasi carattere che non sia un costituente di una parola.<
e>
trova la stringa vuota solo all'inizio o alla fine di una parola rispettivamente;b
corrisponde a entrambi eB
corrisponde a doveb
no.
Nota che gli strumenti senza il |
operatore non hanno la piena potenza delle espressioni regolari. I backreference consentono alcune cose extra che non possono essere fatte con le espressioni regolari in senso matematico.
Espressioni regolari estese (ERE)
Le espressioni regolari estese sono codificate dallo standard POSIX. Il loro principale vantaggio rispetto a BRE è la regolarità:tutti gli operatori standard sono semplici segni di punteggiatura, una barra rovesciata prima che un carattere di punteggiatura lo citi sempre. È la sintassi usata da awk
, grep -E
o egrep
, GNU sed -r
e il =~
di bash operatore. Questa sintassi fornisce le seguenti caratteristiche:
^
e$
corrisponde solo all'inizio e alla fine di una riga..
corrisponde a qualsiasi carattere (o qualsiasi carattere eccetto una nuova riga).[…]
corrisponde a qualsiasi carattere elencato tra parentesi (set di caratteri). Complementazione con un^
iniziale e gli intervalli funzionano come in BRE (vedi sopra). Le classi di caratteri possono essere utilizzate ma mancano in alcune implementazioni. Le moderne implementazioni supportano anche classi di equivalenza ed elementi di confronto. Una barra rovesciata tra parentesi cita il carattere successivo in alcune ma non in tutte le implementazioni; usa\
per significare una barra rovesciata per la portabilità.(…)
è un gruppo sintattico, da utilizzare con*
oDIGIT
sostituzioni.|
in alternativa:foo|bar
corrisponde afoo
obar
.*
,+
e?
corrisponde al carattere o alla sottoespressione precedente un numero di volte:0 o più per*
, 1 o più per+
, 0 o 1 per?
.- La barra rovesciata cita il carattere successivo se non è alfanumerico.
{m,n}
corrisponde al carattere o alla sottoespressione precedente tra m e n tempi (mancanti da alcune implementazioni); n o io può essere omesso e{m}
significa esattamente m .- Alcune estensioni comuni come in BRE:
DIGIT
backreferences (in particolare assenti in awk tranne che nell'implementazione di busybox dove puoi usare$0 ~ "(...)\1"
); caratteri specialin
,t
, eccetera.; confini delle paroleb
eB
, costituenti delle paroleb
eB
, …
PCRE (espressioni regolari compatibili con Perl)
PCRE sono estensioni di ERE, originariamente introdotte da Perl e adottate da GNU grep -P
e molti strumenti e linguaggi di programmazione moderni , di solito tramite la libreria PCRE. Vedi la documentazione Perl per una bella formattazione con esempi. Non tutte le funzionalità dell'ultima versione di Perl sono supportate da PCRE (ad es. l'esecuzione di codice Perl è supportata solo in Perl). Consultare il manuale PCRE per un riepilogo delle funzioni supportate. Le principali aggiunte a ERE sono:
(?:…)
è un gruppo che non cattura:come(…)
, ma non conta per i backreference.(?=FOO)BAR
(lookahead) corrisponde aBAR
, ma solo se esiste anche una corrispondenza perFOO
partendo dalla stessa posizione. Questo è molto utile per ancorare una corrispondenza senza includere il seguente testo nella corrispondenza:foo(?=bar)
corrisponde afoo
ma solo se è seguito dabar
.(?!FOO)BAR
(lookahead negativo) corrisponde aBAR
, ma non c'è nemmeno una corrispondenza perFOO
nella stessa posizione. Ad esempio(?!foo)[a-z]+
corrisponde a qualsiasi parola minuscola che non inizia confoo
;[a-z]+(?![0-9)
corrisponde a qualsiasi parola minuscola che non sia seguita da una cifra (quindi infoo123
, corrisponde afo
ma nonfoo
).(?<=FOO)BAR
(lookbehind) corrisponde aBAR
, ma solo se è immediatamente preceduto da una corrispondenza perFOO
.FOO
deve avere una lunghezza nota (non puoi usare operatori di ripetizione come*
). Questo è molto utile per ancorare una corrispondenza senza includere il testo precedente nella corrispondenza:(?<=^| )foo
corrisponde afoo
ma solo se è preceduto da uno spazio o dall'inizio della stringa.(?<!FOO)BAR
(lookbehind negativo) corrisponde aBAR
, ma solo se non è immediatamente preceduto da una corrispondenza perFOO
.FOO
deve avere una lunghezza nota (non puoi usare operatori di ripetizione come*
). Questo è molto utile per ancorare una corrispondenza senza includere il testo precedente nella corrispondenza:(?<![a-z])foo
corrisponde afoo
ma solo se non è preceduta da una lettera minuscola.
Emac
La sintassi di Emacs è intermedia tra BRE ed ERE. Oltre a Emacs, è la sintassi predefinita per -regex
in GNU trova. Emacs offre i seguenti operatori:
^
,$
,.
,[…]
,*
,+
,?
come in ERE(…)
,|
,{…}
,DIGIT
come in BRE- altre sequenze di lettere backslash;
<
e>
per i confini delle parole; e altro nelle versioni recenti di Emacs, che spesso non sono supportate in altri motori con una sintassi simile a Emacs.
Globi di shell
I glob della shell (caratteri jolly) eseguono il pattern matching con una sintassi completamente diversa dalle espressioni regolari e meno potente. Oltre alle shell, questi caratteri jolly sono disponibili con altri strumenti come find -name
e filtri di sincronizzazione. I modelli POSIX includono le seguenti caratteristiche:
?
corrisponde a qualsiasi singolo carattere.[…]
è un set di caratteri come nelle comuni sintassi delle espressioni regolari. Alcune shell non supportano le classi di caratteri. Alcune shell richiedono!
invece di^
per negare l'insieme.*
corrisponde a qualsiasi sequenza di caratteri (spesso tranne/
quando si abbinano i percorsi dei file; se/
è escluso da*
, quindi**
a volte include/
, ma controlla la documentazione dello strumento).- Barra rovesciata cita il carattere successivo.
Ksh offre funzionalità aggiuntive che conferiscono al suo modello la piena potenza delle espressioni regolari. Queste funzionalità sono disponibili anche in bash dopo aver eseguito shopt -s extglob
. Zsh ha una sintassi diversa ma può anche supportare la sintassi di ksh dopo setopt ksh_glob
.