cat e il flusso di testo: da dove arrivano i dati
Un filtro è un programma che legge testo dallo standard input, lo trasforma e lo scrive sullo standard output. È il cuore della filosofia Unix: tanti programmi piccoli che fanno una cosa sola e si incastrano fra loro con la pipe.
cat (da concatenate) è il più semplice: senza argomenti ripete quello che digiti, con uno o più file li riversa in sequenza sull’output.
$ cat elenco.txt
$ cat parte1.txt parte2.txt
$ cat -n elenco.txt
Attenzione a un vezzo diffuso: cat file | grep testo funziona, ma grep testo file fa la stessa cosa con un processo in meno. In gergo si chiama useless use of cat e negli esercizi LPI viene fatto notare. Nota anche che cat -n numera tutte le righe, mentre nl per impostazione predefinita salta quelle vuote: se un conteggio non torna, il colpevole spesso è questo. Per i file compressi esistono i fratelli zcat (gzip), bzcat (bzip2) e xzcat (xz), che leggono senza decomprimere su disco.
head, tail e wc: tagliare le estremità e contare
head mostra le prime dieci righe di un file, tail le ultime dieci. Il numero si cambia con -n.
$ head -n 5 /etc/passwd
$ tail -n 5 /etc/passwd
$ tail -n +2 dati.csv
Quel -n +2 è la forma che quasi nessuno ricorda e che serve sempre: parte dalla riga 2, cioè scarta l’intestazione di un CSV. head -c 100 taglia invece per byte anziché per righe.
tail -f segue un file mentre cresce ed è il modo standard di guardare un log in diretta. Qui però il percorso cambia con la famiglia: su Debian e Ubuntu il log generale è /var/log/syslog, su Red Hat e derivate è /var/log/messages. E sui sistemi con systemd molti messaggi finiscono nel journal binario, dove servirà journalctl invece di tail.
wc conta: righe con -l, parole con -w, byte con -c e caratteri con -m. Senza opzioni stampa i primi tre valori insieme.
$ grep -c processor /proc/cpuinfo
$ grep processor /proc/cpuinfo | wc -l
Le due righe rispondono alla stessa domanda: quanti processori vede il sistema. Ricorda solo che wc -l conta i caratteri di fine riga, quindi un file la cui ultima riga non termina con un a capo risulta di una riga più corto.
cut, sort e uniq: la catena che risponde alle domande
cut estrae colonne. Con -d indichi il delimitatore, che deve essere un solo carattere, e con -f i campi; con -c tagli invece per posizione dei caratteri. Se ometti -d, il separatore è la tabulazione.
$ cut -d: -f1 /etc/passwd
$ cut -d: -f1,7 /etc/passwd
$ cut -c 1-8 elenco.txt
sort ordina: -n in ordine numerico e non alfabetico (senza, 10 viene prima di 9), -r al contrario, -u scartando i duplicati, -f ignorando maiuscole e minuscole, -t per scegliere il separatore e -k il campo su cui ordinare.
$ sort -t: -k3 -n /etc/passwd
uniq elimina le righe ripetute, -c le conta, -d mostra solo quelle duplicate, -u solo quelle uniche. E qui la trappola più frequente dell’intero obiettivo: uniq confronta soltanto righe adiacenti. Su un file non ordinato non funziona come ti aspetti, per questo lo si vede quasi sempre preceduto da sort.
$ cut -d: -f7 /etc/passwd | sort | uniq -c | sort -nr
Questa catena risponde a “quali shell sono in uso e quanti utenti le usano”, ordinate per frequenza. Imparala: è il modello di quasi ogni domanda pratica su questo obiettivo.
tr e sed: sostituire caratteri contro sostituire pattern
tr lavora carattere per carattere su due insiemi della stessa lunghezza. Ha una particolarità che l’esame ama: non accetta nomi di file, legge solo dallo standard input.
$ tr 'a-z' 'A-Z' < elenco.txt
$ tr -d ' ' < elenco.txt
$ ls -l /etc | tr -s ' '
-d cancella i caratteri indicati, -s (squeeze) comprime le ripetizioni in una sola occorrenza: quest’ultima è la premessa obbligata quando vuoi passare a cut un output separato da spazi multipli, come quello di ls -l.
sed è lo stream editor e ragiona per righe e per pattern. Le forme da conoscere sono tre:
$ sed -n '/bash/p' /etc/passwd
$ sed '/nologin/d' /etc/passwd
$ sed 's/cat/dog/g' elenco.txt
La prima stampa solo le righe che contengono bash: senza -n, sed stamperebbe tutto e le righe trovate due volte, quindi -n e il comando p viaggiano sempre in coppia. La seconda cancella dall’output le righe che corrispondono. La terza sostituisce, e senza il flag finale g cambierebbe solo la prima occorrenza di ogni riga.
Puoi indirizzare le righe per numero e usare $ per l’ultima, e puoi modificare il file sul posto con -i.
$ sed -n '1,10p' elenco.txt
$ sed -i.backup 's/cat/dog/' elenco.txt
Con -i.backup l’originale viene salvato come elenco.txt.backup; con il solo -i viene sovrascritto senza rete di salvataggio. Se il testo contiene barre, cambia separatore: sed 's|/bin|/usr/bin|' è perfettamente valido.
Sono tutte forme da ricordare esatte, non da riconoscere: nelle domande a completamento la differenza fra -n messo e dimenticato vale l’intera risposta.