GNU/Linux: tagliare le stringhe con cut

Oggi un comando spesso sottovalutato che trovo comodissimo in un sacco di occasioni. Si scrive cut, come tagliare (e non cat, il gatto che conosciamo per leggere il contenuto dei file, ma come sempre i gatti c’entrano in qualche modo). cut fa un lavoro semplicissimo: preleva determinate porzioni dalle righe di un file. Ragiona per righe, come altri comandi visti sul canale.

Per gli esempi usiamo lista.txt, un file con una lista di nomi, cognomi ed età separati da tabulazioni. Se non ce l’hai, creane uno (il punto della puntata è il comando, non i dati):

printf 'Mario\tRossi\t30\nLuisa\tBianchi\t25\n' > lista.txt

Lo leggiamo con cat:

cat lista.txt

La sintassi

cut vuole delle opzioni e un file su cui lavorare:

cut OPZIONI file

Tagliare per byte E per caratteri

Con -b si estraggono i primi byte di ogni riga. Prendiamo i byte da 1 a 3 di ogni riga:

cut -b 1-3 lista.txt

Qual è la differenza fra byte e caratteri? In certe codifiche un carattere è definito da più byte. cut ha anche un’opzione, -n, che serve a non dividere i caratteri multibyte. Per i primi tre caratteri esiste -c, e con caratteri semplici il risultato è identico:

cut -c 1-3 lista.txt

È una funzione utile soprattutto nei file a larghezza fissa di colonna, perché permette di estrarre in modo programmatico proprio i campi che ci interessano.

Si possono specificare più range separandoli con la virgola. Il primo carattere e poi i caratteri da 3 a 5:

cut -c 1,3-5 lista.txt

L’output è un po’ strano (Mrio, Lisa), ma è esattamente quello che abbiamo chiesto.

Tagliare per campi

cut sa anche ragionare su file con dei delimitatori, cioè divisi in campi. Il delimitatore di default è la tabulazione, e il nostro file è proprio delimitato da tab. Per avere solo il secondo e il terzo campo si usa -f:

cut -f 2,3 lista.txt

Altri delimitatori

E se il file è delimitato da un altro carattere, per esempio da virgole come un CSV? Nessun problema. Creiamo un CSV con cat e tr, vecchia conoscenza, che sostituisce la tabulazione con una virgola:

cat lista.txt | tr '\t' ',' > lista.csv
cat lista.csv

Se lanciamo il comando di prima otteniamo un pasticcio, perché cut non riesce a capire quali sono i campi:

cut -f 2,3 lista.csv

Gli diciamo allora che il delimitatore, con -d, è la virgola:

cut -d , -f 2,3 lista.csv

Il complemento

Come altri comandi, cut supporta il complemento (–complement), che inverte la selezione. Se faccio la stessa richiesta con –complement ottengo soltanto il campo non nominato dall’opzione -f, cioè il primo:

cut -d , --complement -f 2,3 lista.csv

Range aperti

I range possono essere aperti: si omette il primo o il secondo numero per dire “da” oppure “fino a”. Dal secondo campo fino alla fine della riga:

cut -d , -f 2- lista.csv

Dall’inizio della riga fino al secondo campo:

cut -d , -f -2 lista.csv

È comodo quando sai fino a quale colonna vuoi arrivare, o da quale colonna partire, e per il resto ti va bene andare dall’inizio o fino alla fine della riga.

Cambiare il delimitatore in uscita

Si può anche ottenere un output con un delimitatore diverso. Per esempio devo passare un CSV da Linux a Windows, dove il separatore è il punto e virgola. Con –output-delimiter:

cut -d , --output-delimiter=';' -f 1- lista.csv

Il delimitatore dell’output non è più la virgola ma il punto e virgola. Il pignolo noterà che lo stesso CSV di prima, partendo dal file con le tabulazioni, si poteva ottenere con cut anziché con tr:

cut --output-delimiter=, -f 1- lista.txt

Una delle cose che amo di più dei sistemi Linux è proprio questa: non c’è mai un solo modo scolpito nella pietra, lo stesso risultato si ottiene in tantissimi modi. Alcuni più efficienti, ma la scelta è anche questione di stile e di come imposti i problemi.

Link e risorse

Sostieni il canale

PER SOSTENERE IL CANALE BASTANO UN LIKE E UN’ISCRIZIONE!

questi link sono affiliati Amazon, acquistando i libri che ti consiglio sostieni il canale!