Je fusionne deux fichiers csv. Par souci de simplicité, je n'affiche que les colonnes pertinentes. Il y a plus de quatre colonnes dans les deux fichiers.
file_a.csv
col2, col6, col7, col17, , col18 a, b, c, 145 , 88 e, f, g, 101 , 96
file_b.csv
awk -F, 'NR == FNR {a[$2,$6,$7] = $17;next;} {if (! (b = a[$2,$6,$7])) b = "N/A";print $0,FS,b;}' file_a.csv file_b.csv > out.csv
Sortie devrait ressembler à ceci:
col2, col6, col7, col17, col18 a, b, c, 145, 88 e, f, g, 101, 96
Ainsi, col17 de file_b est ajouté à file_a en tant que col18 lorsque le contenu de col2, col6 et col7 correspond.
J'ai essayé ceci:
col2, col6, col7, col17 a, b, c, 88 e, f, g, 96 x, k, l, 222
La sortie ressemble à ceci:
col2, col6, col7, col17 a, b, c, 145 e, f, g, 101 x, y, z, 243
La colonne 17 de file_b que j'essaie d'ajouter fait être ajouté mais apparaît sur une nouvelle ligne.
Je pense que c'est parce qu'il y a des retours chariot après chaque ligne de file_a et file_b. Dans Notepad ++, je peux voir CRLF. Mais je ne peux pas m'en débarrasser. De plus, je préfère ne pas passer par deux étapes: se débarrasser d'abord des retours chariot, puis fusionner. Au lieu de cela, si je peux contourner les retours chariot pendant la fusion, ce sera beaucoup plus rapide.
Aussi, j'apprécierai si vous pouviez me dire comment me débarrasser des espaces avant et après la virgule séparant la colonne fusionnée. Notez que je mets des espaces entre les colonnes et des virgules pour les autres colonnes pour une meilleure lisibilité. Ce n'est pas comme ça dans les fichiers réels. Mais il y a bien des espaces entre col17 et "," et col18 dans le fichier fusionné et je ne sais pas pourquoi.
Si vous insistez pour marquer cela comme un doublon, veuillez expliquer dans un commentaire ci-dessous comment le les réponses aux questions précédentes traitent de mon problème. J'ai essayé de le comprendre à partir de ces questions similaires précédentes et j'ai échoué.
4 Réponses :
Essayez ceci s'il vous plaît (GNU awk):
awk -F, -v RS="[\r\n]+" 'NR == FNR {a[$2,$6,$7] = $17;next;} {b=a[$2,$6,$7]; print $0 FS (b? b : "N/A")}' file_a.csv file_b.csv
Le problème sur lequel vous avez un problème:
1. Retour chariot, par RS = "[\ r \ n] +"
, il traitera plusieurs sauts de ligne, y compris \ r
et \ n code > comme séparateurs de ligne. Notez que cela ignorera également les lignes vides, si vous ne le souhaitez pas, remplacez par
RS = "\ r \ n"
.
2. Les espaces, c'est parce que OFS
par défaut de awk est un espace. Et lorsque vous imprimez, vous avez utilisé ,
, cela ajoutera des espaces entre eux. Utilisez simplement l'espace ou parfois, écrivez-les ensemble fera l'affaire, ils seront concaténés.
Pourriez-vous essayer de suivre.
awk -v RS="[\r\n]+" ' BEGIN{ SUBSEP=OFS=", " } FNR==NR{ if(FNR==1){ header=$0 } a[$1,$2,$3]=$4 next } FNR==1 && FNR!=NR{ split(header,array,", ") sub(/[a-zA-Z]+/,"",array[4]) print header,"col"array[4]+1 next } a[$1,$2,$3]{ print $0,a[$1,$2,$3] }' b.csv a.csv
À quoi sert le code ci-dessus:
1- On dirait vous pouvez avoir des retours chariot dans votre (vos) fichier (s) d'entrée, j'ai donc créé \ r \ n
comme séparateur d'enregistrement (au cas où vous voudriez supprimer les retours chariot, essayez tr -d '\ r temp && mv temp a.csv
et faites aussi pour les autres fiels).
2- Cela créera également un en-tête selon la dernière colonne de votre fichier.
avec Miller ( http://johnkerl.org/miller/doc )
# file_a.csv col2,col6,col7,col17 a,b,c,145 e,f,g,101 x,y,z,243 # file_b.csv col2,col6,col7,col17 a,b,c,88 e,f,g,96 x,k,l,222
vous avez
col2,col6,col7,col17,col18 a,b,c,145,88 e,f,g,101,96
J'ai utilisé comme entrée
mlr --csv join -j col2,col6,col7 --lp l --rp r -f file_a.csv \ then unsparsify --fill-with "" \ then rename lcol17,col17,rcol17,col18 file_b.csv
Je ne pense pas que «join» permette de faire correspondre les csvs basés sur plusieurs colonnes à moins que vous ne concaténiez les colonnes. Vous l'avez peut-être fait ci-dessus, mais je ne suis pas familier avec le code de jointure et je ne peux donc pas le dire avec certitude. Merci d'avoir tenté de répondre à ma question.
C'est la jointure à l'intérieur de Miller et cela fonctionne en fonction de plusieurs colonnes. Essayez-le
Puisque vous vouliez obtenir des espaces entre le délimiteur ,
, vous pouvez essayer cette solution Perl, qui supprime les espaces lors du fractionnement.
La réponse suppose que vous avez \ r dans les fichiers. J'ai utilisé l'option
-vT
pour cat
pour montrer que le retour chariot existe
$ cat -vT file_a.csv col2, col6, col7, col17^M a, b, c, 145^M e, f, g, 101^M x, y, z, 243^M $ cat -vT file_b.csv col2, col6, col7, col17^M a, b, c, 88^M e, f, g, 96^M x, k, l, 222^M $ $ perl -lne 'BEGIN { %kv=map{chomp;chop;@a=split(/\s*,\s*/);"$a[0],$a[1],$a[2]"=>"$a[3]"} qx(cat file_b.csv) } chop;@b=split(/\s*,\s*/);$x="$b[0],$b[1],$b[2]"; print "$x,$b[-1],",$kv{$x} if $kv{$x} ' file_a.csv col2,col6,col7,col17,col17 a,b,c,145,88 e,f,g,101,96 $