Se passi un po' di tempo davanti a un terminale Linux, prima o poi ti trovi a dover cercare qualcosa: una riga in un log da centomila righe, una variabile di configurazione dimenticata, un indirizzo IP in mezzo a un file di testo. Per tutto questo esiste grep, uno degli strumenti più vecchi e più utili del mondo Unix.
Cos'è grep
grep legge un testo (da uno o più file, oppure dallo standard input) e stampa solo le righe che corrispondono a un modello di ricerca. Il nome viene da un comando dell'editor ed: g/re/p, cioè global / regular expression / print. Nasce nel 1973 ed è stato scritto da Ken Thompson. Su Linux trovi la versione GNU, che fa parte del progetto GNU ed è software libero.
La sintassi di base è:
grep [opzioni] "modello" [file...]Primi esempi
Cerchiamo la parola errore in un file di log:
grep "errore" /var/log/syslogOgni riga che contiene la parola viene stampata. Semplice.
Se il file è protetto, serve sudo:
sudo grep "Failed password" /var/log/auth.logUtilissimo per vedere chi sta provando a indovinare le password SSH del tuo server.
Le opzioni da conoscere
Le opzioni rendono grep potente. Queste sono quelle che uso più spesso.
-i: ignora maiuscole e minuscole
grep -i "salerno" articolo.txtTrova Salerno, SALERNO e salerno.
-n: mostra il numero di riga
grep -n "listen" /etc/nginx/nginx.confPerfetto quando devi poi aprire il file con un editor e andare dritto alla riga giusta.
-v: inverti la ricerca
Mostra le righe che non contengono il modello. Ottimo per togliere i commenti da un file di configurazione:
grep -v "^#" /etc/ssh/sshd_config-c: conta le corrispondenze
grep -c "404" access.logRestituisce quante righe contengono 404, senza stamparle.
-r (o -R): ricerca ricorsiva nelle cartelle
grep -rn "password" /var/www/miosito/Cerca in tutti i file sotto la cartella. Molto comodo per scovare dove è definita una funzione in un progetto, o per controllare di non aver lasciato credenziali in chiaro nel codice.
-l: elenca solo i nomi dei file
grep -rl "TODO" ~/progetti/-w: parola intera
grep -w "log" file.txtTrova log ma non login né catalogo.
-A, -B, -C: contesto attorno alla riga
grep -C 3 "segmentation fault" debug.logStampa la riga trovata più 3 righe prima e 3 dopo. -A è after, -B è before, -C è context (entrambi). Fondamentale quando analizzi i log, perché l'errore da solo spesso non basta: serve capire cosa è successo prima.
-o: stampa solo la parte che corrisponde
grep -oE "[0-9]{1,3}(\.[0-9]{1,3}){3}" access.logEstrae solo gli indirizzi IP (in modo approssimativo) invece di stampare tutta la riga.
Espressioni regolari
Il vero punto di forza di grep sono le espressioni regolari (regex). Qualche simbolo essenziale:
| Simbolo | Significato |
|---|---|
^ | inizio riga |
$ | fine riga |
. | un carattere qualsiasi |
* | zero o più ripetizioni del carattere precedente |
[abc] | uno dei caratteri tra parentesi |
[0-9] | una cifra |
Con -E (regex estese, equivalente a egrep) hai anche +, ?, | e le parentesi di raggruppamento senza dover usare backslash:
# righe che iniziano con "Error" o "Warning"
grep -E "^(Error|Warning)" app.log
# indirizzi email, in modo grossolano
grep -oE "[A-Za-z0-9._-]+@[A-Za-z0-9.-]+\.[a-z]{2,}" contatti.txtSe invece cerchi una stringa letterale che contiene caratteri speciali (punti, parentesi, asterischi), usa -F:
grep -F "192.168.1.1" file.txtSenza -F il punto varrebbe "qualsiasi carattere". Con -F il testo è preso alla lettera, ed è anche più veloce.
-P abilita le regex compatibili con Perl (lookahead, \d e così via), ma dipende dalla build di grep installata.
grep in pipeline: il suo habitat naturale
Il bello di grep è che si combina con gli altri comandi tramite la pipe |.
Trovare un processo:
ps aux | grep firefoxCercare un pacchetto installato:
dpkg -l | grep -i owncastControllare la cronologia dei comandi:
history | grep ffmpegFiltrare l'output di journalctl:
journalctl -u nginx --since today | grep -i "error"Classifica degli IP più attivi in un access log:
grep -oE "^[0-9.]+" access.log | sort | uniq -c | sort -rn | headContare quanti file .md contengono una parola:
grep -rl "trasparenza" --include="*.md" . | wc -lL'opzione --include (e il suo contrario --exclude, oppure --exclude-dir=.git) limita la ricerca a certi tipi di file. Con -r evita di setacciare binari e cartelle inutili.
Quando usare grep
grep è la scelta giusta quando:
- devi filtrare o cercare testo in file, log o output di altri comandi;
- vuoi verificare rapidamente se qualcosa è presente (basta controllare l'exit code:
0se trova,1se non trova); - scrivi script di shell e ti serve una condizione basata sul contenuto di un file;
- lavori su un server remoto via SSH, dove grep c'è sempre e non devi installare nulla.
Esempio d'uso in uno script:
if grep -q "PermitRootLogin yes" /etc/ssh/sshd_config; then
echo "Attenzione: login root via SSH abilitato"
fiL'opzione -q (quiet) non stampa nulla: restituisce solo l'exit code.
Quando non basta
grep è uno strumento per cercare, non per modificare né per elaborare campi.
- Per sostituire del testo usa
sed. - Per lavorare su colonne e campi (per esempio la terza colonna di un CSV) usa
awkocut. - Per grandi codebase esistono alternative più veloci e più comode, come
ripgrep(rg), che rispetta.gitignore, ignora i binari ed è parallelizzato. Un'altra èag(The Silver Searcher). - Per dati strutturati come JSON, è meglio
jq: usare grep su JSON funziona finché non incontri un a capo inatteso.
Piccole trappole
- Le virgolette contano. Metti sempre il modello tra virgolette: senza, la shell può interpretare caratteri come
*o$prima che arrivino a grep. - grep e se stesso. In
ps aux | grep firefoxcompare anche la riga del comando grep. Trucco classico:grep "[f]irefox", oppure usa direttamentepgrep firefox. - File binari. Se grep dice
Binary file matches, aggiungi-aper trattarlo come testo, oppure-Iper ignorare i binari. - Codifiche. Con testi in UTF-8 e lingue con accenti, controlla che la tua locale (
echo $LANG) sia coerente, altrimenti-ipuò comportarsi in modo strano con le lettere accentate.
Riepilogo veloce
| Obiettivo | Comando |
|---|---|
| Cerca una parola | grep "parola" file |
| Ignora maiuscole | grep -i |
| Numero di riga | grep -n |
| Righe senza la parola | grep -v |
| Ricerca nelle cartelle | grep -rn "parola" cartella/ |
| Solo nomi dei file | grep -rl |
| Contesto attorno | grep -C 3 |
| Regex estese | grep -E |
| Testo letterale | grep -F |
| Solo la parte trovata | grep -o |
grep ha più di cinquant'anni e fa ancora esattamente quello per cui è stato progettato: una cosa sola, fatta bene. Impararne le dieci opzioni principali ti fa risparmiare ore di lavoro, che tu stia analizzando i log di un server, controllando la configurazione di un servizio o cercando in un archivio di documenti. È anche un ottimo punto di partenza per entrare nel mondo delle espressioni regolari, che ti torneranno utili in sed, awk, nei linguaggi di programmazione e negli editor di testo.
Per approfondire: man grep, oppure grep --help per un promemoria rapido.