#howto - Gestire i CSV da terminale

Scritto da il
Redatto da
CSV
bash
terminale

A lavoro mi capita di gestire sempre una certa quantità di CSV e similari, alle volte anche di una certa dimensione.

Spesso e volentieri, decido di farlo tramite terminale per automatizzare e velocizzare alcune operazioni.

sort

Il comando sort permette di ordinare da linea di comando in maniera veloce e semplice i file di testo, eventualmente indicando anche dei criteri di ordinamento.

ad esempio il comando:

echo "alberto
giovanni
giacomo
aldo  
zurli
davide
zio   
pera" | sort

Restituirà:

alberto
aldo
davide
giacomo
giovanni
pera
zio
zurli

Tuttavia, per applicare il comando ai file CSV, bisogna applicare alcune opzioni al comando.
Le principali opzioni di sort da conoscere per manipolare i CSV sono:

  • -t quest’opzione serve per impostare il separatore, nel caso dei csv se seguono il formato standard, sarà -t,.
  • -k quest’opzione serve a richiedere uno specifico campo quando c’è un separatore. Usato in coppia con l’opzione -t permette di ordinare rispetto ad una determinata cella separata con il carattere indicato da t, altrimenti il separatore standard è lo spazio.
  • -g Quest’opzione può essere utilizzata per richiedere l’ordinamento numerico e non quello alfanumerico, utile per le celle numeriche.
  • -r per ordinare al contrario (ordine decrescente).
  • -u elimina le occorrenze doppie, se usato in combo con -k, lo fa tenendo conto della cella selezionata

Supponendo di avere un csv siffatto:

alberto,alberti, 32
giovanni,storti, 67
giacomo,poretti, 68
aldo,baglio, 66
zurli,mago, 150
davide,galati, 33
zio,pera, 21
pera,zio, 21

Cioè nome,cognome,età.

Supponendo di dover ordinare per cognome si può scrivere:

sort -t, -k2 nomicognomieta.csv 

Output:

alberto,alberti, 32
aldo,baglio, 66
davide,galati, 33
zurli,mago, 150
zio,pera, 21
giacomo,poretti, 68
giovanni,storti, 67
pera,zio, 21

O per età, dal più grande al più piccolo:

sort -t, -k3 -g -r nomicognomieta.csv

Che come risultato:

zurli,mago, 150
giacomo,poretti, 68
giovanni,storti, 67
aldo,baglio, 66
davide,galati, 33
alberto,alberti, 32
zio,pera, 21
pera,zio, 21

Provando ad eliminare le righe con la stessa età:

sort -t, -k3 -g -r -u nomicognomieta.csv

Che da come risultato:

zurli,mago, 150
giacomo,poretti, 68
giovanni,storti, 67
aldo,baglio, 66
davide,galati, 33
alberto,alberti, 32
zio,pera, 21

column

Column serve a mostrare i dati in input in colonne, seguendo una specifica formattazione. Non necessita di troppe opzioni, quelle utili ai CSV sono:

  • -s che imposta il delimitatore dei campi. Ad esempio -s, legge la virgola come delimitatore.
  • -t che organizza i dati con tabella e allineamento a sinistra.

Supponendo di avere un csv siffatto:

alberto,alberti, 32
giovanni,storti, 67
giacomo,poretti, 68
aldo,baglio, 66
zurli,mago, 150
davide,galati, 33
zio,pera, 21
pera,zio, 21

Scrivendo:

column -s, -t < nomicognomieta.csv

Si avrà:

alberto   alberti   32
aldo      baglio    66
davide    galati    33
zurli     mago      150
zio       pera      21
giacomo   poretti   68
giacomo   poretti   32
giovanni  storti    67
pera      zio       21

Ma se il file contiene molti file resta comunque molto scomodo leggerlo senza poterlo navigare. Potrebbe essere utile appendere il comando less con le seguenti opzioni:

  • -# che seguito da un numero imposta il numero di spazi tra una cella e un altra. Ad esempio -#2 mette due spazi.
  • -N che serve a mostrare il numero di riga per ogni riga del CSV
  • -S che fa si che si possa navigare “orizzontalmente” nel csv (questa opzione potrebbe essere di default in molte implementazioni di less)

Scrivendo dunque:

column -s, -t < nomicognomieta.csv| less -#2 -N -S

Si potrà navigare in totale comodità il file csv senza alcun problema

awk

Considero awk lo strumento “definitivo” per la modifica di una grande mole di dati, riesce a processare riga per riga. È presente sul sito una guida completa su AWK.

Awk rappresenta anche un ottimo metodo per manipolare i dati su csv. Le cose che si possono fare usandolo sono limitate solo dalla fantasia e non si possono trattare tutte ovviamente, ma vediamo come si può utilizzare per fare un parsing e qualche calcolo.

Innanzitutto per leggere un file csv l’unica opzione da utilizzare è -F seguita dal delimitatore. Ad esempio con F ',' leggeremo i csv separati per virgola.

Supponendo il seguente csv:

alberto,alberti, 32
giovanni,storti, 67
giacomo,poretti, 68
aldo,baglio, 66
zurli,mago, 150
davide,galati, 33
zio,pera, 21
pera,zio, 21

Si può ad esempio tirare fuori così l’età media:

awk -F ',' '
{
        somma+=$3
}

END{
        media=somma/NR
        print("eta media",media)
}' nomicognomieta.csv

Per trovare il più anzino:

awk -F ',' '       
BEGIN {
        max=-1
        maxname=""
}
{
        if(max<$3){
                maxname=$1
                max=$3
        }
}

END{
        print("il più anziano del gruppo si chiama",maxname,"ed ha",max,"anni")
}' nomicognomieta.csv

Extra: excel con gnumeric

Purtroppo il formato più utilizzato per tabelle dati è diventato nel tempo quello proprietario di excel. Lo svantaggio di questa tipologia di dati è che oltre ad essere proprietario è anche binario, quindi non facilmente leggibile, questo induce a chiedersi come fare a leggere questi dati al di fuori di piattaforme Microsoft.

Nel tempo son nati molti software (proprietari o meno) in grado di leggere gli excel come Libreoffice, WPS, open office etc… così come molte librerie.

Su linux esiste il software in GTK gnumeric che si può installare tramite i vari package manager, tramite questo si può convertire poi, anche a linea di comando, un excel in csv e processarlo tramite i metodi sopra elencati:

Installazione gnumeric Ubuntu e derivate

Per installare gnumeric su Ubuntu e derivate scrivere

apt install gnumeric

Installazione gnumeric Fedora

Per installare gnumeric su Fedora scrivere

dnf install gnumeric

Installazione gnumeric ArchLinux

Per installare gnumeric su ArchLinux scrivere

pacman -S gnumeric

Conversione

Per convertire un excel in csv scrivere:

ssconvert file_excel.xlsx file_excel_convertito.csv

Extra: excel con python xlsx2csv

Un altro tool utilizzabile è xlsx2csv, scritto in python ed installabile tramite pip:

pip install xlsx2csv

Oppure tramite pipx se si è su ArchLinux:

pipx install xlsx2csv

Utilizzabile poi scrivendo:

xlsx2csv file_excel.xlsx > file_excel_convertito.csv

Considerazioni finali

I file CSV sono talvolta piuttosto ostici da utilizzare, principalmente perché il formato presenta molte varianti.
Per esempio, normalmente contengono un header con i nomi delle colonne nella prima riga del file, oppure utilizzano i doppi apici - spesso opzionali - per raggruppare i caratteri di stringhe che contengono i delimitatori. Per esempio:

ID,Nome,Cognome,Indirizzo
1,Paolo,Rossi,"via Paolo, 3"
2,Marco,Bianchi,via Marco Polo

Queste casistiche si possono pensare di trattare con non banali combinazioni di comandi come sort, head, tail e awk, oltre a gestire il tutto con python.
Per esempio, in casi semplici, il comando

head -n 1 file.csv

estrae la prima riga dal file file.csv, che potrebbe corrispondere all’header.
Il condizionale è dovuto al fatto che l’header non è obbligatorio nei file CSV, e potrebbe non essere presente, come nei molti esempi presentati in questo articolo.

Quando il formato di un file CSV si fa complicato, oppure le operazioni da svolgere sono non banali, come ad esempio l’unione di due file diversi utilizzando criteri opportuni, ci si può affidare - sempre dalla linea di comando - a strumenti specifici per i file CSV.
Alcuni esempi sono i seguenti:

  • csvkit, una suite di comandi per convertire e manipolare i file CSV.
  • csvtk, un singolo programma scritto in linguaggio Go, che mette a disposizione parecchi sotto-comandi per manipolare i file CSV.
  • tabview, un programma in Python che usa la libreria ncurses per la visualizzazione di file CSV da terminale.
history_edu Revisioni