GNU/Linux >> Linux Esercitazione >  >> Linux

Come analizzare i file CSV negli script Bash in Linux

Valori separati da virgola alias CSV è un dato semistrutturato che utilizza la virgola come delimitatore per separare le parole. I formati di file CSV sono molto popolari tra i professionisti dei dati poiché devono gestire molti file CSV ed elaborarli per creare approfondimenti. In questo articolo, ci concentreremo su come analizzare i file CSV negli script della shell Bash in Linux.

Nella maggior parte delle parti di questo articolo utilizzerò awk e sed strumenti per l'analisi CSV invece di combinare comandi diversi come grep , cut , tr , ecc.

Il awk l'utilità riduce la complessità del piping di più comandi o della scrittura di un ciclo con la logica per acquisire i dati. Invece, puoi scrivere un codice one-liner in awk per fare il lavoro.

1. Preparazione del file CSV per l'elaborazione

Il tuo file CSV potrebbe essere generato da un database, un'API o potresti aver eseguito alcuni comandi e convertito l'output in delimitare in formato CSV. In ogni caso, devi prima analizzare il set di dati prima di eseguire la tua logica su di esso.

Come best practice, dovresti pulire il tuo set di dati prima di usarlo. Perché dovremmo pulire il set di dati? Potrebbero esserci situazioni in cui ci saranno valori di celle vuote o nessuna formattazione corretta nelle intestazioni, colonne extra che non sono necessarie per l'elaborazione e molti altri.

Sto utilizzando i seguenti dati CSV, che ho preso da Kaggle a scopo dimostrativo.

Player_Id,Player_Name,DOB,Batting_Hand,Bowling_Skill,Country
1,SC Ganguly,8-Jul-72,Left_Hand,Right-arm medium,
2,BB McCullum,27-Sep-81,Right_Hand,Right-arm medium,
3,RT Ponting,19-Dec-74,Right_Hand,Right-arm medium,
4,DJ Hussey,15-Jul-77,Right_Hand,Right-arm offbreak,Australia
5,Mohammad Hafeez,17-Oct-80,,Right-arm offbreak,Pakistan
6,R Dravid,11-Jan-73,,Right-arm offbreak,India
7,W Jaffer,16-Feb-78,,Right-arm offbreak,India
8,V Kohli,5-Nov-88,,Right-arm medium,India
9,JH Kallis,16-Oct-75,,Right-arm fast-medium,South Africa
10,CL White,18-Aug-83,Right_Hand,Legbreak googly,Australia
11,MV Boucher,3-Dec-76,Right_Hand,Right-arm medium,South Africa
12,B Akhil,7-Oct-77,Right_Hand,Right-arm medium-fast,India
13,AA Noffke,30-Apr-77,Right_Hand,Right-arm fast-medium,Australia
14,P Kumar,2-Oct-86,Right_Hand,Right-arm medium,India
15,Z Khan,7-Oct-78,Right_Hand,Left-arm fast-medium,India

1.1. Sostituisci celle vuote

In alcuni casi, il file CSV non conterrà alcun valore in determinate celle. Dai un'occhiata allo screenshot qui sotto dove ci sono alcune celle vuote tra le colonne.

Lo sostituirei sempre con "NA" o "Nessun valore", quindi non ci saranno celle vuote. Puoi usare il seguente awk snippet per sostituire qualsiasi cella vuota con il valore desiderato. In questo caso, sto sostituendo le celle vuote con "Nessun valore".

awk 'BEGIN{FS=",";OFS=","}
    {
      for(i=1;i<=NF;i++)
      {
        if($i == ""){
         $i="No Value"
        }
      }
      print
    }' ~/Downloads/Player.csv > player_cleaned.csv

Il modo in cui funziona questo snippet è che sto impostando il separatore di campo e il separatore di campo di output su virgola (FS=",";OFS="," ). Usando for loop , scorrere ogni cella in una riga e, se una cella viene trovata vuota ($i == "" ) quindi sostituirlo con "No value" ($i="No value" ). Devi reindirizzare le modifiche a un nuovo file.

Lettura consigliata:

  • Il reindirizzamento di Bash spiegato con esempi

1.2. Metti in maiuscolo l'intestazione

I file CSV possono avere o meno intestazioni. Ma se c'è un'intestazione, la metterei sempre in maiuscolo per una migliore leggibilità. Puoi farlo facilmente usando awk o sed . Ti mostrerò entrambi i modi.

awk 'BEGIN{FS=",";OFS=","}
    {
        if(NR==1){
            print toupper($0)
        } else {
            print
        }
    }' player.csv > player_cleaned.csv

Qui stiamo controllando se la riga è di prima riga usando(NR==1 ) e utilizzando toupper() funzione per capitalizzarlo. Lo stesso snippet può essere scritto come una riga.

awk 'NR==1{ print toupper($0) }NR>1' player.csv > player_cleaned.csv

Usando awk , devi reindirizzare nuovamente le modifiche a un nuovo file. Invece, puoi usare 'sed ' per modificare le modifiche direttamente nel file. Qui \U converte le maiuscole in maiuscolo. Se vuoi eseguire la conversione in minuscolo, usa \L .

$ sed -i -e '1 s/(.*)/\U\1/' player_cleaned.csv
$ cat player_cleaned.csv

1.3. Rimuovi la virgola finale

Il tuo file CSV potrebbe contenere una virgola alla fine. Per pulire le virgole finali, puoi seguire il metodo seguente.

Ho aggiunto di proposito una virgola finale dalle righe 7 a 11 nel mio file di dati.

Per rimuovere tutte le virgole finali, esegui il seguente sed comando:

$ sed -i 's/,$//' ~/Documents/player_cleaned.csv

Ora abbiamo finito con la parte di pulizia. Potrebbero essere necessari alcuni passaggi in più per te, ma ciò dipende da come è strutturato il tuo file CSV e da cosa deve essere pulito.

2. File CSV Pretty Print nel terminale

Se stai cercando di visualizzare i file CSV nel terminale, ci sono alcune opzioni in cui puoi stampare il file in formato tabulare che ti darà una migliore leggibilità.

2.1. Comando Colonna

Il primo approccio consiste nell'utilizzare la column comando. Il comando Colonna accetta un separatore che è impostato su virgola e un delimitatore per dividere la colonna che è impostata su tab nel comando seguente. Puoi anche impostare i tuoi delimitatori personalizzati.

$ cat player_cleaned.csv | column -s, -t
$ column -s, -t player_cleaned.csv

2.2. Comando Guarda CSV

Csvlook è un'utilità fornita con il pacchetto csvkit. Non è necessario impostare un delimitatore come abbiamo fatto con la column comando.

$ cat player_cleaned.csv | csvlook
$ csvlook player_cleaned.csv

2.3. Python Pretty Table

Se hai il python prettytable modulo installato, quindi puoi eseguire il seguente one-liner e reindirizzare il file CSV per generare la tabella.

python -c "import sys,prettytable; print(prettytable.from_csv(sys.stdin))" < player_cleaned.csv

Puoi anche creare un alias per il one-liner e passare il nome del file come argomento.

$ alias ptable='python -c "import sys,prettytable; print(prettytable.from_csv(sys.stdin))"'
$ ptable < player_cleaned.csv

3. Acquisizione di dati da file CSV

3.1. Stampa conteggio righe e colonne

Per ottenere il numero di colonne nel file CSV, eseguire il comando seguente. Qui la variabile NF rappresenta il numero di campi divisi da una virgola come delimitatore.

$ awk -F, 'END{print NF}' player_cleaned.csv
6

Per ottenere il numero di righe, eseguire il comando seguente. Qui la variabile NR rappresenta il record corrente (cioè) ogni riga è considerata come un record.

$ awk -F, 'END{print NR}' player_cleaned.csv
16

Per saltare la prima riga (intestazione) e calcolare il numero di righe, eseguire il comando seguente.

$ awk -F, 'END{print NR-1}' player_cleaned.csv
15

3.2. Stampa l'intero file CSV

Questo è abbastanza semplice. Puoi usare cat o awk per stampare l'intero file CSV.

$ cat player_cleaned.csv
$ awk '{print}' player_cleaned.csv

3.3. Stampa solo intestazione da file CSV

La stampa dell'intestazione da sola ti darà una buona panoramica del tipo di dati che contiene il tuo file CSV. Puoi usare il head o awk comando per catturare l'intestazione da solo.

$ head -n 1 player_cleaned.csv
$ awk 'NR==1' player_cleaned.csv

PLAYER_ID,PLAYER_NAME,DOB,BATTING HAND,BOWLING SKILL,COUNTRY

3.4. Escludi riga di intestazione

Per escludere la riga di intestazione e stampare tutte le altre righe usa awk comando. La variabile awk NR > 1 farà saltare la prima riga.

$ awk '(NR>1)' player_cleansed.csv

Sed può essere utilizzato anche per escludere la prima riga e stampare tutte le altre righe. Il 1d flag cancellerà la prima riga e stamperà tutte le altre righe su stdout (Terminale).

$ sed 1d < player_cleaned.csv

3.5. Stampa colonne particolari

Possiamo usare la posizione della colonna per stampare l'intera colonna. Ci sono due approcci per raggiungere questo obiettivo. Il primo approccio sarà utilizzare awk e il secondo approccio sarà quello di utilizzare loop . Awk sarà molto più semplice afferrare la colonna.

Awk per impostazione predefinita divide la riga in base al delimitatore e memorizza i valori in $1 , $2 , $3 , ecc. Il delimitatore predefinito per awk è spazio bianco .

Dai un'occhiata allo snippet di seguito in cui il separatore di campo(FS="," ) e separatore del campo di output(OFS="," ) è impostato su virgola. L'istruzione print stamperà la prima colonna, la seconda colonna e la sesta colonna.

awk 'BEGIN{FS=",";OFS=","}
    {
        print $1,$2,$6
    }' player_cleansed.csv

Puoi anche scrivere lo snippet sopra in una riga.

awk 'BEGIN{FS=",";OFS=","}{print $1,$2,$6}' player_cleansed.csv

Ora il secondo approccio sarebbe quello di utilizzare i loop.

IFS="," 
while read -r -a fields
do
    echo ${fields[0]},${fields[1]},${fields[5]}
done < player_cleaned.csv

Lascia che ti spieghi cosa succede esattamente quando esegui lo snippet sopra.

  • Stiamo impostando l'IFS separatore di campo interno su virgola.
  • Usando il comando di lettura stiamo creando un array chiamato "fields" e reindirizzando il file di input al while loop .
  • Per ogni iterazione, leggerà riga per riga e memorizzerà la riga come elementi dell'array nei "campi" in modo da poter utilizzare la posizione dell'indice dell'array per afferrare solo la particolare colonna.

Nota: Il valore dell'indice inizia da 0..N

3.6. Stampa riga che corrisponde alla condizione

Se desideri stampare le righe che soddisfano una determinata condizione, puoi farlo facilmente utilizzando awk . Esaminiamo alcuni scenari.

Per stampare tutte le righe che corrispondono a un valore in una colonna, eseguire il comando seguente. Qui sto cercando di stampare tutte le righe che corrispondono al valore "India" nella colonna 6.

$ awk -F , '$6 == "India"' player_cleaned.csv

Per stampare tutte le righe che non corrispondono a un determinato valore, eseguire il comando seguente. Invece di un operatore di uguaglianza , stiamo usando operatore non uguale .

$ awk -F , '$6 != "India"' player_cleaned.csv

Puoi anche eseguire un controllo delle condizioni su più di una colonna utilizzando l'operatore logico AND, OR logico. Diciamo che voglio controllare tutte le righe che hanno il paese come "India" e la mano in battuta come "Right_hand".

Qui, $4 punta alla 4a colonna e $6 indica la sesta colonna. Il simbolo && viene utilizzato come operatore AND logico per valutare due condizioni.

$ awk -F , '$4 == "Right_Hand" && $6 == "India"' player_cleaned.csv

Se desideri includere l'intestazione insieme al risultato del controllo condizionale, utilizza il comando seguente. Per prima cosa sto stampando la prima riga usando NR==1 , quindi utilizzando l'operatore AND logico che esegue il controllo condizionale per stampare i risultati.

$ awk 'NR==1' player_cleaned.csv && awk -F , '$4 == "Right_Hand" && $6 == "India"' player_cleaned.csv

Se desideri stampare o reindirizzare l'output, esegui l'intero comando all'interno di una subshell racchiudendolo tra parentesi .

$ (awk 'NR==1' player_cleaned.csv && awk -F , '$4 == "Right_Hand" && $6 == "India"' player_cleaned.csv) | column -t -s,

Una nota su Csvkit

Finora tutto ciò che abbiamo visto in questo articolo è semplice e diretto. Ma quando il tuo file CSV ha una struttura complessa, diventa noioso analizzare usando l'approccio sopra. Esiste un'utilità chiamata CSVKIT , che è un'eccellente utility per lavorare con i file CSV in bash.

Il problema con l'utilità csvkit è che è installata per impostazione predefinita nella distribuzione e potrebbe essere necessario installarla manualmente. Nel tuo ambiente aziendale, ciò potrebbe non essere possibile poiché potrebbero esserci alcune restrizioni all'installazione di pacchetti esterni. Ma questa utilità vale la pena menzionarla e creeremo un articolo dettagliato separato per questo.

Conclusione

In questa guida abbiamo visto come lavorare con i file CSV usando awk, sed. Puoi anche usare altre utilità come cut, grep, tr, ecc. per ottenere il risultato desiderato, ma awk e sed ti semplificheranno la vita e ridurranno la complessità della scrittura di molti codici. Se hai qualche feedback, menzionalo nella sezione commenti e saremo felici di sentirlo da te.

Lettura simile:

  • Scripting Bash:analisi degli argomenti negli script Bash utilizzando getopts
  • Come analizzare e stampare in modo grazioso JSON con gli strumenti della riga di comando di Linux

Linux
  1. Come rinominare i file in Linux

  2. Come abbreviare il prompt di Bash in Linux?

  3. Come comprimere più file su Linux

  4. Come la shell BASH carica i suoi file di configurazione in Linux

  5. Come analizzare un file CSV in Bash?

Come rinominare file e directory in Linux

Come rinominare uno o più file in Linux

Come eseguire il debug di script Bash in Linux e Unix

Script di shell per principianti - Come scrivere script Bash in Linux

Come utilizzare il comando echo negli script Bash in Linux

Come comprimere un file in Linux