J'ai deux fichiers csv file1.csv
et file2.csv
.
file1.csv
contient 4 colonnes.
file1:
awk -F'"(,")?' ' NR==FNR { r[$2] = $3; next } { for (n in r) gsub(n,r[n]) } IGNORECASE=1' file2.csv file1.csv>output.csv
fichier2:
cat,dog,ccccccc,ddddddd eeeeeee,fffffff,ggggggg,hhhhhhh doctor,engineer,kkkkkkk,lllllll sky,blue,ooooooo,ppppppp
Donc, ce que j'essaie de faire est de lire file1.csv
ligne par ligne, de placer chaque entrée dans un tableau puis de comparer le premier élément de ce tableau avec la première colonne de file2.csv code> et si une correspondance existe, remplacez la colonne1 et la colonne2 de fichier1.csv par la colonne correspondante de fichier2.csv
Donc, ma sortie souhaitée est:
"Header1","Header2","Header3" "aaaaaaa","cat","dog" "iiiiiii","doctor","engineer" "mmmmmmm","sky","blue"
Je peux le faire lorsqu'il n'y a qu'une colonne à remplacer.
Voici mon code:
Header1,Header2,Header3,Header4 aaaaaaa,bbbbbbb,ccccccc,ddddddd eeeeeee,fffffff,ggggggg,hhhhhhh iiiiiii,jjjjjjj,kkkkkkk,lllllll mmmmmmm,nnnnnnn,ooooooo,ppppppp
Ma dernière étape consiste à vider le tableau entier dans un fichier de 10 colonnes. Des suggestions pour améliorer ou corriger mon code?
3 Réponses :
EDIT: Considérant que votre Input_file2 a la date au format "ytest", "test2"
etc si oui, essayez de suivre. (Merci à Tiw d'avoir fourni ces exemples dans son message) XXX
Pourriez-vous s'il vous plaît essayer de suivre.
awk ' BEGIN{ FS=OFS="," } FNR==NR{ a[tolower($1)]=$0 next } a[tolower($1)]{ print a[tolower($1)],$NF next } 1' Input_file2 Input_file1
OU au cas où vous pourriez avoir une combinaison de lettres minuscules et majuscules dans Input_file (s) puis essayez de suivre.
awk ' BEGIN{ FS=OFS="," } FNR==NR{ a[$1]=$0 next } a[$1]{ print a[$1],$NF next } 1' Input_file2 Input_file1
Merci pour les efforts que j'expérimente avec votre code en ce moment.
Compte tenu de vos exemples de données et de la description de vos commentaires, veuillez essayer ceci:
(À en juger par votre propre code, vous pouvez avoir des guillemets autour des champs, donc je n'ai pas essayé de répondre.)
awk 'BEGIN{FS=OFS=","} NR==FNR{gsub(/^"|"$/,"");gsub(/","/,",");k=tolower($1);a[k]=$2;b[k]=$3;next} {k=tolower($1);if(a[k]){$2=b[k];$1=a[k]}} 1' file2.csv file1.csv
Eg:
awk 'BEGIN{FS=OFS=","} NR==FNR{for(i=1;i<=NF;i++)$i=gensub(/^"(.*)"$/,"\\1",1,$i);a[$1]=$2;b[$1]=$3;next} $1 in b{$2=b[$1];} $1 in a{$1=a[$1];} 1' file2.csv file1.csv
Une autre façon, plus verbeuse, mais je pense que c'est mieux pour vous de comprendre (GNU awk):
$ cat file1.csv Header1,Header2,Header3,Header4 aaaaaaa,bbbbbbb,ccccccc,ddddddd eeeeeee,fffffff,ggggggg,hhhhhhh iiiiiii,jjjjjjj,kkkkkkk,lllllll mmmmmmm,nnnnnnn,ooooooo,ppppppp $ cat file2.csv "Header1","Header2","Header3" "aaaaaaa","cat","dog" "iiiiiii","doctor","engineer" "mmmmmmm","sky","blue" $ awk 'BEGIN{FS=OFS=","} NR==FNR{gsub(/^"|"$/,"");gsub(/","/,",");a[$1]=$2;b[$1]=$3;next} $1 in a{$2=b[$1];$1=a[$1];} 1' file2.csv file1.csv Header2,Header3,Header3,Header4 cat,dog,ccccccc,ddddddd eeeeeee,fffffff,ggggggg,hhhhhhh doctor,engineer,kkkkkkk,lllllll sky,blue,ooooooo,ppppppp
Notez un piège ici, puisque $ 1 code > est la clé, nous devrions donc changer
$ 1
en dernier.
Une solution insensible à la casse:
awk 'BEGIN{FS=OFS=","} NR==FNR{gsub(/^"|"$/,"");gsub(/","/,",");a[$1]=$2;b[$1]=$3;next} $1 in a{$2=b[$1];$1=a[$1];} 1' file2.csv file1.csv
Pour un code concis, ajout de la variable k
et déplacement de "if"
à l'intérieur.
merci comme vous l'avez dit, la deuxième méthode était plus facile à comprendre. J'ai essayé de l'utiliser et cela fonctionne.
@AnujKulkarni Bien sûr, je suis content que cela ait aidé :)
Avec n'importe quel awk et n'importe quel nombre de champs dans l'un ou l'autre fichier:
$ cat tst.awk BEGIN { FS=OFS="," } { gsub(/"/,"") key = tolower($1) } NR==FNR { for (i=2; i<=NF; i++) { map[key,i] = $i } next } { for (i=2; i<=NF; i++) { $(i-1) = ((key,i) in map ? map[key,i] : $(i-1)) } print } $ awk -f tst.awk file2 file1 Header2,Header3,Header3,Header4 cat,dog,ccccccc,ddddddd eeeeeee,fffffff,ggggggg,hhhhhhh doctor,engineer,kkkkkkk,lllllll sky,blue,ooooooo,ppppppp
Le code dans le bloc NR == FNR
stocke les valeurs de file2
dans le tableau de la carte un champ à la fois et la boucle dans le 2ème bloc accède aux valeurs de ce tableau un champ à la fois.
En voyant votre profil, vous avez appris que, parmi les dernières questions, vous ne sélectionnez aucune réponse comme bonne, alors demandez-vous de le faire (après un certain temps après votre publication) et lorsque vous voyez suffisamment de réponses à votre message, vous pouvez sélectionner n'importe qui des répondez correctement à l'un d'entre eux @Anuj Kulkarni
@Tiw oui mon fichier2.csv peut avoir des guillemets. Je crée moi-même file2.csv tandis que file1.csv est un fichier généré par un outil. Ainsi, lors de la création de file2.csv, j'avais utilisé des guillemets.
@Tiw oui c'est correct. Il n'y aura pas de virgule. J'utilise les guillemets car file2 peut avoir plus de deux mots séparés par des espaces (comme une phrase).
@AnujKulkarni. Il est toujours conseillé de publier des échantillons proches du ou des Input_file (s), veuillez modifier votre message et nous le faire savoir.
Anul si votre entrée est séparée par des virgules, alors un vide ou une tabulation est comme n'importe quel autre caractère, vous n'avez pas besoin de mettre des guillemets autour de vos champs sauf s'ils contiennent une virgule ou une nouvelle ligne. Peuvent-ils contenir des nouvelles lignes?
@EdMorton non, il n'y aura pas de nouvelles lignes.