Introduzione
Il comando grep
che sta per "global regular expression print" è uno dei comandi più potenti e comunemente usati in Linux.
Grep cerca uno o più file di input alla ricerca di linee che corrispondono a un determinato modello e scrive ciascuna riga corrispondente sullo standard output. Se non viene specificato alcun file, grep
legge l'input standard, che di solito è l'output di un altro comando.
In questo tutorial, ti mostreremo come usare il comando grep
attraverso esempi pratici e spiegazioni dettagliate delle opzioni grep
GNU più comuni.
Sintassi del comando Grep
Prima di andare su come utilizzare il comando grep
, iniziamo esaminando la sintassi di base.
La sintassi di grep
assume la seguente forma:
grep [OPTIONS] PATTERN [FILE...]
Gli elementi tra parentesi quadre sono opzionali.
OPTIONS
- Zero o più opzioni. Grep offre una serie di opzioni che ne controllano il comportamento.PATTERN
- Modello di ricerca.FILE
- Zero o più nomi di file di input.
Per poter cercare il file, l'utente che esegue il comando deve avere accesso in lettura al file.
Come utilizzare grep per cercare una stringa nei file
L'uso più basilare del comando grep
è la ricerca di una stringa (text) in un file.
Ad esempio, per visualizzare le righe dal file /etc/passwd
contenente la stringa bash
è possibile utilizzare il comando seguente:
grep bash /etc/passwd
L'output dovrebbe assomigliare a questo:
root:x:0:0:root:/root:/bin/bash
noviello:x:1000:1000:noviello:/home/noviello:/bin/bash
Se la stringa include spazi, è necessario racchiuderla tra virgolette singole o doppie:
grep "Gnome Display Manager" /etc/passwd
Invert Match (Escludi)
Per visualizzare le linee che non corrispondono al valore cercato, utilizzare l'opzione -v
(o --invert-match
).
Ad esempio, per visualizzare le righe del file /etc/passwd
che non contengono la stringa nologin
è possibile utilizzare il comando seguente:
grep -v nologin /etc/passwd
root:x:0:0:root:/root:/bin/bash
colord:x:124:124::/var/lib/colord:/bin/false
git:x:994:994:git daemon user:/:/usr/bin/git-shell
noviello:x:1000:1000:noviello:/home/noviello:/bin/bash
Come usare Grep per cercare una stringa nell'output dei comandi
Invece di specificare i file di input, è possibile reindirizzare l'output di un altro comando verso grep
e quindi visualizzare solo le righe corrispondenti a un determinato modello.
Ad esempio, per scoprire quali processi sono in esecuzione sul sistema come utente, www-data
è possibile utilizzare il comando ps
seguente :
ps -ef | grep www-data
www-data 18247 12675 4 16:00 ? 00:00:00 php-fpm: pool www
root 18272 17714 0 16:00 pts/0 00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn www-data
www-data 31147 12770 0 Oct22 ? 00:05:51 nginx: worker process
www-data 31148 12770 0 Oct22 ? 00:00:00 nginx: cache manager process
Puoi anche concatenare più pipe su comando. Come puoi vedere nell'output sopra c'è anche una riga che contiene il processo grep
. Se non si desidera visualizzare quella riga, passare l'output a un'altra istanza grep
, come mostrato di seguito.
ps -ef | grep www-data | grep -v grep
www-data 18247 12675 4 16:00 ? 00:00:00 php-fpm: pool www
root 18272 17714 0 16:00 pts/0 00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn www-data
www-data 31147 12770 0 Oct22 ? 00:05:51 nginx: worker process
www-data 31148 12770 0 Oct22 ? 00:00:00 nginx: cache manager process
Ricerca ricorsiva (Recursive Search)
Per cercare in modo ricorsivo un modello utilizzare, utilizzare l'opzione -r
(o --recursive
). Questo cercherà tra tutti i file nella directory specificata, saltando i collegamenti simbolici che si incontrano in modo ricorsivo. Per seguire tutti i collegamenti simbolici, utilizzare l'opzione -R
(o --dereference-recursive
).
Nel seguente esempio stiamo cercando la stringa noviello.it
in tutti i file all'interno della directory /etc
:
grep -r noviello.it /etc
Il comando stamperà le righe corrispondenti precedute dal percorso completo del file.
/etc/hosts:127.0.0.1 node2.noviello.it
/etc/nginx/sites-available/noviello.it: server_name noviello.it www.noviello.it;
Se invece di usare l'opzione -r
usi l'opzione -R
il comando grep
seguirai tutti i collegamenti simbolici:
grep -R noviello.it /etc
Si noti l'ultima riga dell'output. Quella riga non viene stampata nell'esempio sopra perché i file all'interno della directory sites-enabled
di Nginx sono collegamenti simbolici ai file di configurazione all'interno della directory sites-available
.
/etc/hosts:127.0.0.1 node2.noviello.it
/etc/nginx/sites-available/noviello.it: server_name noviello.it www.noviello.it;
/etc/nginx/sites-enabled/noviello.it: server_name noviello.it www.noviello.it;
Mostra solo il Filename
Per sopprimere l'output grep
predefinito e stampare solo i nomi dei file contenenti il modello corrispondente, è possibile utilizzare l'opzione -l
(o --files-with-matches
).
Ad esempio, per cercare tra tutti i file che terminano con .conf
nella directory di lavoro corrente e stampare solo i nomi dei file contenenti il tipo di stringa noviello.it
:
grep -l noviello.it *.conf
L'output sarà simile al seguente:
tmux.conf
haproxy.conf
L'opzione -l
viene generalmente utilizzata in combinazione con l'opzione ricorsiva -R
:
grep -Rl noviello.it /tmp
Ricerca senza distinzione tra maiuscole e minuscole (Insensitive)
Per impostazione predefinita, il comando grep
fa distinzione tra maiuscole e minuscole. Ciò significa che i caratteri maiuscoli e minuscoli sono trattati come distinti.
Per ignorare il caso durante la ricerca, utilizzare l'opzione -i
(o --ignore-case
).
Ad esempio, quando si cerca Zebra
senza alcuna opzione, il comando seguente non mostrerà alcun output, ovvero ci sono linee corrispondenti:
grep Zebra /usr/share/words
Ma se esegui una ricerca senza distinzione tra maiuscole e minuscole utilizzando l'opzione -i
, corrisponderà alle lettere maiuscole e minuscole:
grep -i Zebra /usr/share/words
Specificare "Zebra" corrisponderà a "zebra", "ZEbrA" o qualsiasi altra combinazione di lettere maiuscole e minuscole per quella stringa.
zebra
zebra's
zebras
Ricerca di parole complete
Durante la ricerca di "gnu", grep
stamperà le righe in cui "gnu" è incorporato in parole più grandi, come "cygnus" o "magnum".
grep gnu /usr/share/words
cygnus
gnu
interregnum
lgnu9d
lignum
magnum
magnuson
sphagnum
wingnut
Per restituire solo quelle righe in cui la stringa specificata è una parola intera (racchiusa da caratteri non di parole), utilizzare l'opzione -w
(o --word-regexp
).
I caratteri di parola includono caratteri alfanumerici (a-z
, A-Z
e 0-9
) e caratteri di sottolineatura (_
). Tutti gli altri caratteri sono considerati caratteri non di parole.
Se si esegue lo stesso comando di cui sopra, inclusa l'opzione -w
, il comando grep
restituirà solo quelle righe in cui gnu
è incluso come parola separata.
grep -w gnu /usr/share/words
gnu
Mostrare numeri di riga
Per mostrare il numero delle linee che contengono una stringa che corrisponde a un modello, utilizzare l'opzione -n
(o --line-number
). Quando si utilizza questa opzione, grep
stamperà le corrispondenze sull'output standard con prefisso con il numero di riga sul quale è stata trovata.
Ad esempio, per visualizzare le righe dal file /etc/services
contenente la stringa bash
con il prefisso con il numero di riga corrispondente è possibile utilizzare il comando seguente:
grep -n 10000 /etc/services
L'output di seguito mostra che le corrispondenze si trovano sulle righe 10423 e 10424.
10423:ndmp 10000/tcp
10424:ndmp 10000/udp
Conteggio risultati
Per stampare un conteggio delle righe corrispondenti all'output standard, utilizzare l'opzione -c
(o --count
).
Nell'esempio seguente, stiamo contando il numero di account che hanno /usr/bin/zsh
come shell.
grep -c '/usr/bin/zsh' /etc/passwd
3
Cercare più stringhe (pattern)
È possibile unire due o più modelli di ricerca utilizzando l'operatore OR |
.
Per impostazione predefinita, grep
interpreta il modello come un'espressione regolare di base in cui i meta-caratteri come |
perdono il loro significato speciale e devono essere utilizzate le loro versioni rovesciate.
Nell'esempio riportato di seguito stiamo cercando tutte le occorrenze delle parole fatal
, error
e critical
nel file di registro di errore di Nginx:
grep 'fatal\|error\|critical' /var/log/nginx/error.log
Se si utilizza l'opzione di espressione regolare estesa -E
(o --extended-regexp
), l'operatore |
non deve essere salvato, come mostrato di seguito:
grep -E 'fatal|error|critical' /var/log/nginx/error.log
Modalità silenziosa
Il -q
(o --quiet
) dice grep
di non scrivere nulla sul terminale (output standard). Se viene trovata una corrispondenza, il comando uscirà con lo stato 0
. Ciò è utile quando si utilizza grep
nella shell in cui si desidera verificare se un file contiene una stringa ed eseguire una determinata azione in base al risultato.
Ecco un esempio dell'uso di grep
in modalità non interattiva come comando di test in un'istruzione if
:
if grep -q PATTERN filename
then
echo pattern found
else
echo pattern not found
fi
Espressione regolare di base (Basic Regular Expression)
GNU Grep ha due set di funzioni per le espressioni regolari, Basic ed Extended. Per impostazione predefinita, grep
interpreta il modello come un'espressione regolare di base.
Se utilizzati nella modalità di espressione regolare di base, tutti gli altri caratteri tranne i meta-caratteri sono in realtà espressioni regolari corrispondenti a se stessi. Di seguito è riportato un elenco dei meta-caratteri più comunemente usati:
Utilizzare il simbolo ^
(caret) per abbinare l'espressione all'inizio di una riga. Nel seguente esempio, la stringa ^kangaroo
corrisponderà solo se si verifica all'inizio di una riga.
grep "^kangaroo" file.txt
Utilizzare il simbolo $
(dollaro) per abbinare l'espressione alla fine di una riga. Nel seguente esempio, la stringa kangaroo$
corrisponderà solo se si verifica alla fine di una riga.
grep "kangaroo$" file.txt
Utilizzare il .
simbolo (punto) per abbinare un singolo carattere. Ad esempio, per abbinare tutto ciò che inizia con kan
poi ha due caratteri e termina con la stringa roo
, puoi usare il seguente modello:
grep "kan..roo" file.txt
Utilizzare [ ]
(parentesi) per abbinare qualsiasi carattere singolo racchiuso tra parentesi. Ad esempio, trova le righe che contengono accept
o accent
, puoi utilizzare il seguente modello:
grep "acce[np]t" file.txt
Utilizzare [^ ]
(parentesi) per abbinare qualsiasi carattere singolo racchiuso tra parentesi. Il seguente schema corrisponderà a qualsiasi combinazione di stringhe contenente co(any_letter_except_l)a
, come coca
, cobalt
e così via, ma non corrisponderà le linee contenenti cola
,
grep "co[^l]a" file.txt
Per fare un escape di un carattere speciale successivo, utilizzare il simbolo \
(barra rovesciata).
Espressioni regolari estese (Extended Regular Expressions)
Per interpretare il pattern come un'espressione regolare estesa, utilizzare l'opzione -E
(o --extended-regexp
). Le espressioni regolari estese includono tutti i meta-caratteri di base, insieme a meta-caratteri aggiuntivi per creare schemi di ricerca più complessi e potenti. Di seguito sono riportati alcuni esempi:
Abbina ed estrai tutti gli indirizzi email da un determinato file:
grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" file.txt
Abbina ed estrai tutti gli indirizzi IP validi da un determinato file:
grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' file.txt
L' -o
opzione viene utilizzata per stampare solo la stringa corrispondente.
Stampare righe prima di un risultato
Per stampare un numero specifico di righe prima di abbinare le righe, utilizzare l'opzione -B
(o --before-context
).
Ad esempio, per visualizzare cinque righe di contesto iniziale prima di abbinare le righe, utilizzare il comando seguente:
grep -B 5 root /etc/passwd
Stampare righe dopo un risultato
Per stampare un numero specifico di righe dopo aver abbinato le righe, utilizzare l'opzione -A
(o --after-context
).
Ad esempio, per visualizzare cinque righe di contesto finale dopo aver abbinato le righe, utilizzare il comando seguente:
grep -A 5 root /etc/passwd
Conclusione
Il comando grep
consente di cercare un modello all'interno dei file. Se viene trovata una corrispondenza, grep stamperà le linee contenenti il motivo specificato.