Le basi: pattern, file e flag
Otto opzioni coprono il novanta per cento degli usi reali di grep. Impararle a memoria, insieme al concetto di exit code, vuol dire essere autosufficienti per quasi tutto il resto.
Sintassi, comportamento, exit code
La forma generale di grep è semplice:
grep [OPZIONI] PATTERN [FILE...]
Se non si passa alcun file, grep legge dallo standard input — è la chiave del suo uso in pipe, che vedremo nella lezione 9. Quando i file sono più di uno, grep antepone ad ogni riga il nome del file di provenienza.
Le opzioni che bastano per la stragrande maggioranza dei casi reali sono otto:
| opzione | cosa fa |
|---|---|
| -i | ignora maiuscole/minuscole |
| -n | mostra il numero di riga davanti al match |
| -c | conta le righe che matchano (non i match!) |
| -v | inverte: mostra le righe che NON matchano |
| -l | stampa solo i nomi dei file che contengono almeno un match |
| -L | l'opposto di -l: i file che NON hanno nessun match |
| -w | match solo se è una parola intera |
| -x | match solo se l'intera riga corrisponde |
Una nona, fondamentale per gli script, è -q (quiet): grep
non stampa nulla e termina al primo match. Serve solo per leggere il suo
exit code, che è il modo con cui grep comunica il risultato a chi lo
chiama:
0— è stata trovata almeno una riga che matcha1— nessuna riga matcha2— errore (file inesistente, regex malformata)
Le otto opzioni viste in azione
Mettiamo in piedi un file più sostanzioso e proviamole tutte di seguito:
$ cat > access.log <<'EOF' 2026-05-20 10:01 GET /home 200 2026-05-20 10:02 POST /login 200 2026-05-20 10:03 GET /home 404 2026-05-20 10:04 GET /api/users 500 2026-05-20 10:05 GET /home 200 EOF # -n : numerare le righe $ grep -n 404 access.log 3:2026-05-20 10:03 GET /home 404 # -c : quante righe corrispondono $ grep -c GET access.log 4 # -v : tutto tranne le richieste con status 200 $ grep -v 200 access.log 2026-05-20 10:03 GET /home 404 2026-05-20 10:04 GET /api/users 500 # -i : maiuscole/minuscole indifferenti $ grep -i post access.log 2026-05-20 10:02 POST /login 200
Ora un caso classico in cui -w salva la vita. Cerchiamo la parola
log in un file di configurazione: senza -w matcheremmo
anche login, logout, logger…
$ printf '%s\n' "log=on" "login=true" "log_level=info" | grep log log=on login=true log_level=info $ printf '%s\n' "log=on" "login=true" "log_level=info" | grep -w log log=on
grep -q negli script: il rilevatore silenzioso
Quando vuoi solo sapere se un certo testo c'è dentro un file —
senza vedere il match, senza output — il pattern ideale negli shell script è
grep -q. È più pulito e più veloce di tutte le alternative.
# prima di aggiungere una riga a /etc/hosts, controlla che non ci sia già if grep -q "^192\.168\.1\.10" /etc/hosts; then echo "host già presente" else echo "192.168.1.10 server-locale" | sudo tee -a /etc/hosts fi # controlla se un servizio è attivo if ps aux | grep -q "[n]ginx"; then echo "nginx attivo" fi
[n]ginx invece di nginx:
è uno dei trucchi più amati. La regex [n]ginx matcha esattamente
la stringa nginx, ma il comando grep stesso nella sua riga
del ps contiene [n]ginx, non nginx, e
quindi non si auto-trova. Risultato: niente "grep grep" da escludere a mano.
Lo riprenderemo nella lezione 9.
Combinazione utilissima con -l: trovare in quali file di una cartella
compare un certo testo, ma ricevere solo l'elenco dei file, perfetto per
pipare ad altri comandi:
$ grep -l "TODO" *.py app.py utils.py # apri tutti i file che contengono TODO nel tuo editor $ vim $(grep -l "TODO" *.py)