Espressioni regolari estese
Con -E sblocchi quantificatori, alternanza e gruppi: la sintassi
diventa quella che la maggior parte delle persone si aspetta da una regex
moderna. È quasi sempre quello che vuoi usare.
Quello che BRE non aveva
ERE è l'acronimo di Extended Regular Expression. Si attiva con il flag
-E, oppure usando il comando storico egrep (oggi
deprecato ma ancora presente). Aggiunge quattro cose centrali rispetto a BRE:
| simbolo | significato |
|---|---|
| + | una o più ripetizioni del precedente |
| ? | zero o una occorrenza (rende opzionale) |
| {n} | esattamente n ripetizioni |
| {n,m} | tra n e m ripetizioni |
| a|b | alternanza: a oppure b |
| (…) | gruppo |
In BRE gli stessi simboli si possono ottenere col backslash:
\+, \?, \{n,m\}, \|,
\(…\). Ma è una sintassi pesante e poco leggibile. Per qualsiasi
regex non banale conviene aggiungere -E e finita lì.
+, ?, | o gruppi, scrivi grep -E.
Più chiaro per chi legge, più portabile tra script.
Numeri, versioni, indirizzi
Uno dei classici: trovare numeri di versione in un file di sorgente o
di configurazione. Una versione è qualcosa come 1.2.3 — cifre,
punto, cifre, punto, cifre.
$ cat > release.txt <<'EOF' release 2.4.1 patch 2.4.2 versione iniziale 0.1 ultimo: 12.0.5-rc EOF # una o più cifre, punto, una o più cifre, punto, una o più cifre $ grep -E '[0-9]+\.[0-9]+\.[0-9]+' release.txt release 2.4.1 patch 2.4.2 ultimo: 12.0.5-rc # anche le versioni a due numeri (0.1) — il terzo gruppo è opzionale $ grep -E '[0-9]+\.[0-9]+(\.[0-9]+)?' release.txt release 2.4.1 patch 2.4.2 versione iniziale 0.1 ultimo: 12.0.5-rc
L'alternanza con | è preziosissima per cercare più cose
con una sola passata. Cerchiamo errori, warning e info in un log unico:
$ cat > app.log <<'EOF' [INFO] avvio applicazione [WARN] cache vuota [INFO] connessione db [ERROR] connessione fallita [DEBUG] retry in 5s EOF $ grep -E 'ERROR|WARN' app.log [WARN] cache vuota [ERROR] connessione fallita
Quantificatore preciso con {n,m}. Esempio: trovare codici postali
italiani (esattamente 5 cifre) o americani (5, o 5-4):
$ echo -e "Milano 20121\nRoma 00100\nNYC 10001-1234\ncodice 999" \ | grep -E '\<[0-9]{5}(-[0-9]{4})?\>' Milano 20121 Roma 00100 NYC 10001-1234
Eliminare le righe vuote (e i commenti) da un file
Capita di continuo: vuoi leggere un file di configurazione pulito, senza tutte le
righe vuote e i commenti che lo riempiono. Con grep -E -v si fa in
una riga, ed è una delle combinazioni più riusabili che esistano:
$ cat /etc/ssh/sshd_config # $OpenBSD: sshd_config,v 1.104 ... # questa è una riga di commento Port 22 # AddressFamily any PermitRootLogin no # righe non vuote e non commento $ grep -Ev '^\s*(#|$)' /etc/ssh/sshd_config Port 22 PermitRootLogin no
Il pattern ^\s*(#|$) dice: a inizio riga, eventuali spazi/tab, poi
o un # (commento) o la fine della riga (riga vuota).
Con -v chiediamo l'opposto: tutto ciò che non è quello.
~/.bashrc o ~/.zshrc come
alias conf='grep -Ev "^\s*(#|$)"' — d'ora in poi conf
/etc/nginx/nginx.conf ti mostrerà la configurazione effettiva, senza
rumore. Il tempo che risparmierai a leggere file di configurazione lunghi è
enorme.
Una variante per chi gestisce server: stessa logica applicata a tutta una cartella
con -r (lezione 5) per vedere d'un colpo tutte le direttive attive di
un servizio.