1
votes

Fusion de deux fichiers csv, impossible de se débarrasser de la nouvelle ligne

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é.


0 commentaires

4 Réponses :


1
votes

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.


0 commentaires

0
votes

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.


0 commentaires

0
votes

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


2 commentaires

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



0
votes

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
$


0 commentaires