Supponiamo che io ho due file, en.csv
e sp.csv
, ciascuno contenente esattamente due record separati da virgola:Come ottenere tutti i campi in outer join con Unix join?
en.csv
:
1,dog,red,car
3,cat,white,boat
sp.csv
:
2,conejo,gris,tren
3,gato,blanco,bote
Se eseguo
join -t, -a 1 -a 2 -e MISSING en.csv sp.csv
l'uscita che ottengo è:
1,dog,red,car
2,conejo,gris,tren
3,cat,white,boat,gato,blanco,bote
Si noti che tutti i campi mancanti sono state crollato. Per ottenere un join esterno completo "corretto", ho bisogno di specificare un formato; così
join -t, -a 1 -a 2 -e MISSING -o 0,1.2,1.3,1.4,2.2,2.3,2.4 en.csv sp.csv
cede
1,dog,red,car,MISSING,MISSING,MISSING
2,MISSING,MISSING,MISSING,conejo,gris,tren
3,cat,white,boat,gato,blanco,bote
Un inconveniente di questo modo di produrre un full outer join è che bisogna specificare esplicitamente il formato del tavolo finale, che non può essere facile da fare in programmatica applicazioni (dove l'identità delle tabelle unite è nota solo al runtime).
Le versioni recenti di GNU join
eliminano questa mancanza supportando il formato speciale auto
. Pertanto, con tale versione del join
l'ultimo comando di cui sopra potrebbe essere sostituito dal gran lunga più generale
join -t, -a 1 -a 2 -e MISSING -o auto en.csv sp.csv
Come posso ottenere lo stesso effetto con le versioni di join
che non supportano l'opzione -o auto
?
Background e dettagli
Ho una shell Unix (zsh) script che è stato progettato per processi diversi flatfiles CSV, e lo fa facendo vasta uso di GNU join
's' - o auto 'opzione. Devo modificare questo script in modo che possa funzionare in ambienti in cui il comando disponibile join
non supporta l'opzione -o auto
(come nel caso di BSD join
e nelle versioni precedenti di GNU join
).
Un utilizzo tipico di questa opzione nello script è qualcosa di simile:
_reccut() {
cols="1,$1"
shift
in=$1
shift
if (($# > 0)); then
join -t, -a 1 -a 2 -e 'MISSING' -o auto \
<(cut -d, -f $cols $in | sort -t, -k1) \
<(_reccut "[email protected]")
else
cut -d, -f $cols $in | sort -t, -k1
fi
}
mi mostra questo esempio per illustrare che sarebbe difficile da sostituire -o auto
con un formato esplicito, dal momento che i campi da includere in questo il formato non è noto fino al runtime.
La funzione _reccut
sopra in pratica estrae le colonne dai file e unisce le tabelle risultanti lungo la loro prima colonna.Per vedere come _reccut
in azione, immaginare che, oltre ai file di cui sopra, abbiamo avuto anche il file
de.csv
2,Kaninchen,Grau,Zug
1,Hund,Rot,Auto
Quindi, per esempio, per visualizzare side-by-side colonna 3 en.csv
, colonne 2 e 4 del sp.csv
e colonna 3 de.csv si potrebbe correre:
% _reccut 3 en.csv 2,4 sp.csv 3 de.csv | cut -d, 2-
red,MISSING,MISSING,Rot
MISSING,conejo,tren,Grau
white,gato,bote,MISSING
avendo dovuto fare esattamente ciò che si sta parlando di un progetto 1-off con Sun4, penso che tu sei bloccato con la tua codifica o fornisci un nuovo GNU join come parte della tua installazione. Scusa, ma buona fortuna. – shellter
Immagino che dovrei aggiungere, dopo molti scherzi, ho finito con l'associare array in awk, con molto meno fastidio. In bocca al lupo. – shellter