2014-09-16 6 views
6

Ho due file CSV, voglio unirmi a loro utilizzando un valore chiave, la colonna della città.unire due file CSV con valore chiave

Un file CSV, d01.csv ha questa forma,

Barcelona, 19.5, 29.5 
Tarragona, 20.4, 31.5 
Girona, 17.2, 32.5 
Lleida, 16.5, 33.5 
Vic, 17.5, 31.4 

L'altro, d02.csv, ha la struttura seguente,

City, Data, TMax, TMin 
Barcelona, 20140916, 19.9, 28.5 
Tarragona, 20140916, 21.4, 30.5 
Lleida, 20140916, 17.5, 32.5 
Tortosa, 20140916, 20.5, 30.4 

Ho bisogno di un nuovo file CSV, con una colonna di città che appaiono nei file 2 csv.

City, Tmin, Tmax, Date, Tmin1, Tmax1 
Barcelona, 19.5, 29.5, 20140916, 19.9, 28.5 
Tarragona, 20.4, 31.5, 20140916, 21.4, 30.5 
Girona, 17.2, 32.5, 20140916, 17.5, 32.5 
Lleida, 16.5, 33.5, 20140916, 20.5, 30.4 

ho cercato di farlo con

join -j 2 -t ',' d01.csv d02.csv | awk -F "," '{print $1, $2, $3, $4, $5} > d03.csv 

ma non è completo ... come posso ordinare il valore della chiave?

+0

sono quelli che portano i numeri nel reale File? Qual è l'output di quel comando join? Stai davvero cercando di invertire l'ordine delle colonne 'Tmin' e' Tmax' come parte di questo processo? 'D01.csv' non ha davvero una linea di riferimento? I valori di 'Tmax' dovrebbero essere inferiori ai valori di' Tmin' nei file di input? –

+1

@Jotne Non ho apportato questa modifica perché non ero certo che le virgole iniziali nel primo file fossero un errore. L'OP ha usato '-j 2' nel comando' join' dopo tutto. –

+0

OP Se la modifica è errata, correggerla. – Jotne

risposta

6

Ecco come utilizzare unirsi in bash:

{ 
    echo "City, Tmin, Tmax, Date, Tmin1, Tmax1" 
    join -t, <(sort d01.csv) <(sed 1d d02.csv | sort) 
} > d03.csv 
cat d03.csv 
City, Tmin, Tmax, Date, Tmin1, Tmax1 
Barcelona, 19.5, 29.5, 20140916, 19.9, 28.5 
Lleida, 16.5, 33.5 , 20140916, 17.5, 32.5 
Tarragona, 20.4, 31.5 , 20140916, 21.4, 30.5 

Nota che uniscono emette solo i record in cui esiste la chiave in entrambi i file. Per ottenere tutti loro, specificare che si desidera record mancanti da entrambi i file, specificare i campi che si desidera, e dare un valore predefinito per i campi mancanti:

join -t, -a1 -a2 -o 0,1.2,1.3,2.2,2.3,2.4 -e '?' <(sort d01.csv) <(sed 1d d02.csv | sort) 
Barcelona, 19.5, 29.5, 20140916, 19.9, 28.5 
Girona, 17.2, 32.5,?,?,? 
Lleida, 16.5, 33.5 , 20140916, 17.5, 32.5 
Tarragona, 20.4, 31.5 , 20140916, 21.4, 30.5 
Tortosa,?,?, 20140916, 20.5, 30.4 
Vic, 17.5, 31.4,?,?,? 
+0

Grazie per i comandi e il commento –

+0

Epico pezzo di scripting, grazie! Nel mio caso sembrava aggiungi alcuni ritorni a capo vaganti (che appaiono in vi come^M), ma potrebbe essere correlato ai miei dati di origine.Il seguente comando rapido vi ordina questo: ':% s/\ r // g'. – Tom

+0

Questo comando non avrebbe aggiunto alcun ritorno a capo, sarebbero derivati ​​dai tuoi file di input. –

0

Questo awk può fare:

awk 'FNR==NR {a[$1]=$2FS$3FS$4;next} $1 in a {print $0,a[$1]}' OFS=", " d02,csv d01csv 
Barcelona, 19.5, 29.5, 20140916, 19.9, 28.5 
Tarragona, 20.4, 31.5 , 20140916, 21.4, 30.5 
Lleida, 16.5, 33.5 , 20140916, 17.5, 32.5 
+0

funziona anche, ma potresti spiegarmi questa struttura? Lo apprezzerò –

+0

@EnricAgudPique 'FNR == NR' esegui questo file per il primo file' d02.csv' (memorizza i dati da un file a un array 'a' usando il primo campo come indice.) Quindi se il primo campo viene trovato nel file successivo '$ 1 in a' stampa output necessario.Questo è un modo comune per gestire due file in' awk'. – Jotne

+0

Grazie per il vostro aiuto –