1
votes

Fusion de> 2 fichiers avec AWK ou JOIN?

La fusion de 2 fichiers à l'aide d'AWK est un sujet bien couvert sur StackOverflow. Cependant, la technique de lecture de 3 fichiers dans un tableau devient plus compliquée. Au fur et à mesure que je formate la sortie pour entrer dans un script R, je vais devoir ajouter beaucoup de syntaxe pour ne pas penser que je peux utiliser JOIN. Voici une version simpliste sur laquelle je travaille jusqu'à présent:

word1 <- c(1, 11)
word2 <- c(2, 22)
word3 <- c(3, 22)

Où:

$ cat words.txt
word1
word2
word3

$ cat x.txt
1
2
3

$ cat y.txt
11
22
33

La sortie est alors

awk 'FNR==1{f++}
     f==1{a[FNR]=$1;next}
     f==2{b[FNR]=$1;next}
     {print a[FNR], "<- c(", b[FNR], ",", $1, ")"}' words.txt x.txt y.txt 

La meilleure façon de résumer cette technique est

  1. Créez une variable f pour suivre le fichier que vous traitez
  2. Pour le fichier 1, lisez les valeurs dans le tableau a
  3. Pour le fichier 2, lisez les valeurs dans le tableau b
  4. Passez au fichier trois, où vous concaténez votre sortie finale

En tant que débutant à AWK, cela fonctionne, mais je trouve ça un peu gênant et j'ai peur de revenir au code dans 6 mois, je ne le comprendrai plus. Est-ce la meilleure façon de fusionner ces 3 fichiers dans AWK? JOIN pourrait-il réellement gérer ce niveau de formatage de la sortie finale?


2 commentaires

Pourriez-vous également publier un exemple de sortie dans les balises de code et nous le faire savoir?


J'ai fait: mot1 <- c (1, 11) mot2 <- c (2, 22) mot3 <- c (3, 22)


3 Réponses :


1
votes

EDIT: Pourriez-vous essayer de suivre.

paste words.txt x.txt y.txt 
word1   1   11
word2   2   22
word3   3   33

Le résultat sera le suivant.

word1 <- c(1, 11)
word2 <- c(2, 22)
word3 <- c(3, 33)


Si vous souhaitez simplement ajouter le contenu de 3 fichiers dans la colonne vice, essayez de suivre.

paste words.txt x.txt y.txt | awk '{$2="<- c("$2", "$3")";$3="";sub(/ +$/,"")} 1'


4 commentaires

Merci, mais j'ai explicitement écrit la question pour m'assurer qu'il était clair que j'avais besoin que la sortie soit au format de script R. J'ai besoin que la sortie soit: mot1 <- c (1, 11) mot2 <- c (2, 22) mot3 <- c (3, 22) Votre exemple ne fait pas cela


@ScottJenson, pourriez-vous s'il vous plaît vérifier ma solution EDIT et me le faire savoir?


Merci, cela fonctionne clairement et utilise PASTE, qui est évidemment plus simple pour fusionner les fichiers. Cependant, il faut alors une chaîne AWK assez complexe pour «corriger» le formatage. La solution de @Tiw utilisant ARGIND me semble plus facile car il y a beaucoup plus de contrôle sur la création de la sortie.


@ScottJenson, pas un problème, vous pouvez utiliser la solution la mieux adaptée à votre situation. Voir ce lien également ce qu'il faut faire quand on obtient des réponses utiles sur les applaudissements SO stackoverflow.com/help/someone-answers et continuez à apprendre, continuez à partager.



1
votes

Si c'est pour la lisibilité, vous pouvez changer la méthode de vérification des fichiers, ainsi que les noms des variables.
Essayez ceci s'il vous plaît:

awk 'FILENAME==ARGV[1]{xcol[FNR]=$1;} #Read column B, x column
     FILENAME==ARGV[2]{ycol[FNR]=$1;} # Read column C, y cloumn
     FILENAME==ARGV[3]{print $1, "<- c(", xcol[FNR], ",", ycol[FNR], ")";}' x.txt y.txt words.txt 

La méthode de vérification des fichiers ci-dessus est pour GNU awk.

Passer à un autre, ainsi que modifier l'ordre de lecture des fichiers, serait:

awk 'FILENAME=="words.txt"{print $1, "<- c(", xcol[FNR], ",", ycol[FNR], ")";}
     FILENAME=="x.txt"{xcol[FNR]=$1;}
     FILENAME=="y.txt"{ycol[FNR]=$1;}' x.txt y.txt words.txt 

Comme vous pouvez également le voir ici, l'ordre de lecture des fichiers et le blocage l'ordre peut être différent.
Puisque words.txt a la première colonne, ou colonne principale , pour ainsi dire, il est donc judicieux de le lire en dernier.

Vous pouvez également utiliser FILENAME == ARGV [1] FILENAME == ARGV [2] etc. pour vérifier les fichiers et mettre des commentaires à l'intérieur (utilisez awk fichier de script et charger avec awk -f scriptfile est mieux avec les commentaires):

awk 'ARGIND==1{words[FNR]=$1;}
     ARGIND==2{xcol[FNR]=$1;}
     ARGIND==3{print words[FNR], "<- c(", xcol[FNR], ",", $1, ")"}' words.txt x.txt y.txt


4 commentaires

Merci! Vous «avez» mon besoin de lisibilité et vos suggestions sont toutes excellentes. Il indique également comment ajouter un 4ème fichier (si nécessaire)


@ScottJenson Heureux que cela ait aidé :) Oui, il est facile d'ajouter d'autres fichiers par ces méthodes.


Erreur NOOB, je n'ai pas essayé votre solution avant de répondre. Hélas, je suis sur un Mac et n'utilise pas GNU awk, ARGINT ne semble pas être pris en charge. Cependant, l'astuce FILENAME == ARGV [1] fonctionne. C'est verbeux pour être sûr mais c'est clair. Je vais suivre votre suggestion d'utiliser une entrée de fichier de script afin qu'elle puisse être structurée et commentée, ce qui est beaucoup plus important.


@ScottJenson Eh bien, que diriez-vous de brew install gawk et de commencer à utiliser la commande gawk ;)



2
votes

une variante de la solution de @ RavinderSingh13

$ paste {words,x,y}.txt | awk '{print $1, "<- c(" $2 ", " $3 ")"}'


1 commentaires

Merci. Je suis un peu dépassé par la créativité et le support de Stack Overflow. Ces trois réponses sont utiles. Ce que j'aime dans cette réponse, c'est qu'en utilisant Paste, il peut gérer plus de fichiers (comme l'a fait la solution de @ ravinderSingh) mais en ayant une solution AWK plus simple, il conserve plus de lisibilité que je recherche.