Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 23/03/2020, à 17:41

judkil

AWK_utilliisation de getline et jointure

Bonjour

Je souhaite réaliser une jointure où AWK prendre le nom d'une ligne dans un premier fichier, le placer en champs 1 dans le fichier output, puis va dans un second fichier prend les noms étendus et les place en champs 2.

Voici les Input
fichier_1:
AB-00050832
AB-00058394
AB-00050862
AB-00004123

fichier_2:
AB-00050832-18     1    -8.900758
AB-00058394-10     2    -7.981418
AB-00050832-24     3    -7.634420
AB-00050862-10     4    -7.621671
AB-00004123-1       5    -7.386272
AB-00058394-6       6    -7.383604
AB-00050832-12   14    -7.038594
AB-00050862-6     50    -6.701126

output:
AB-00050832     AB-00050832-18     1    -8.900758
                           AB-00050832-24     3    -7.634420
                           AB-00050832-12   14    -7.038594
AB-00058394     AB-00058394-10     2    -7.981418
                           AB-00058394-6       6    -7.383604
AB-00050862     AB-00050862-10     4    -7.621671
                           AB-00050862-6     50    -6.701126
AB-00004123     AB-00004123-1       5    -7.386272


fichier_2 est
-joint à fichier_1
-retrié en fonction de fichier_1 en suivant l'ordre de fichier_1.
Il est juste important de garder l'ordre dans lequel apparaît le nom dans fichier_1. J'ai essayé avec un getline mais j'ai l'impression qu'il y a quelque chose que je n'arrive pas à débloquer.

Si vous avez une idée, merci beaucoup!

Hors ligne

#2 Le 23/03/2020, à 18:29

kamaris

Re : AWK_utilliisation de getline et jointure

Une méthode qui n'est pas la plus économe, mais bon :

awk 'FILENAME==ARGV[1]{n=FNR; patterns[FNR]=$0} FILENAME==ARGV[2]{m=FNR; OFS="\t"; $(NF+1)=""; lines[FNR]=$0} END{for (i=1;i<=n;i++){ to_print=1; for (j=1;j<=m;j++){ if (lines[j] ~ "^"patterns[i]){ if (to_print){printf("%s\t",patterns[i]); to_print=0}else printf("%s","\t\t"); printf("%s\n",lines[j])}}}}' fichier_1 fichier_2

Voilà ce que ça donne :

$ cat fichier_1
AB-00050832
AB-00058394
AB-00050862
AB-00004123
$ cat fichier_2
AB-00050832-18     1    -8.900758
AB-00058394-10     2    -7.981418
AB-00050832-24     3    -7.634420
AB-00050862-10     4    -7.621671
AB-00004123-1       5    -7.386272
AB-00058394-6       6    -7.383604
AB-00050832-12   14    -7.038594
AB-00050862-6     50    -6.701126
$ awk 'FILENAME==ARGV[1]{n=FNR; patterns[FNR]=$0} FILENAME==ARGV[2]{m=FNR; OFS="\t"; $(NF+1)=""; lines[FNR]=$0} END{for (i=1;i<=n;i++){ to_print=1; for (j=1;j<=m;j++){ if (lines[j] ~ "^"patterns[i]){ if (to_print){printf("%s\t",patterns[i]); to_print=0}else printf("%s","\t\t"); printf("%s\n",lines[j])}}}}' fichier_1 fichier_2
AB-00050832	AB-00050832-18	1	-8.900758	
		AB-00050832-24	3	-7.634420	
		AB-00050832-12	14	-7.038594	
AB-00058394	AB-00058394-10	2	-7.981418	
		AB-00058394-6	6	-7.383604	
AB-00050862	AB-00050862-10	4	-7.621671	
		AB-00050862-6	50	-6.701126	
AB-00004123	AB-00004123-1	5	-7.386272	
$ 

La commande awk en mode développé pour la lisibilité :

awk '
FILENAME==ARGV[1]{n=FNR; patterns[FNR]=$0}
FILENAME==ARGV[2]{m=FNR; OFS="\t"; $(NF+1)=""; lines[FNR]=$0}
END{
  for (i=1;i<=n;i++){
    to_print=1
    for (j=1;j<=m;j++){
      if (lines[j] ~ "^"patterns[i]){
        if (to_print){printf("%s\t",patterns[i]); to_print=0}
        else printf("%s","\t\t")
        printf("%s\n",lines[j])
      }
    }
  }
}' fichier_1 fichier_2

Dernière modification par kamaris (Le 23/03/2020, à 18:53)

Hors ligne

#3 Le 23/03/2020, à 18:31

Watael

Re : AWK_utilliisation de getline et jointure

salut,

J'ai essayé avec un getline mais j'ai l'impression qu'il y a quelque chose que je n'arrive pas à débloquer.

sans ton code, on ne va pas pouvoir t'aider.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#4 Le 23/03/2020, à 18:54

kamaris

Re : AWK_utilliisation de getline et jointure

Désolé : j'étais lancé, du coup j'ai fait l'exo.

Hors ligne

#5 Le 23/03/2020, à 19:13

judkil

Re : AWK_utilliisation de getline et jointure

Voici le début de mon code:

awk' 
BEGIN { i =1
 while  (getline var[i] < "fichier_1.txt" > 0)
 {++i}
 print $0==var print
} '  fichier_2.txt > output.txt

C'est un peu confu, je pense
Merci beaucoup de ton aide, j'ai des notions de débutant en awk, mais que ce passe-t-il dans le code ?
i correspondrait  à une ligne de fichier_1 et j a une ligne de fichier_2. Il y a aussi l'utilisation de ARGV et de patterns que je n'ai pas eu l'occasion de rencontrer.

Dernière modification par judkil (Le 23/03/2020, à 19:13)

Hors ligne

#6 Le 23/03/2020, à 20:49

kamaris

Re : AWK_utilliisation de getline et jointure

La variable spéciale ARGV est documentée dans man awk :

man awk a écrit :

An array of command line arguments, excluding options and the program argument, numbered from zero to ARGC-1.

Donc ARGV est un tableau qui contient la liste des noms de fichiers passés en arguments d'entrée à awk (à partir de ARGV[1], car ARGV[0] contient le nom de la commande appelée, ici « awk »).
Quant à patterns, c'est un tableau que je définis, en choisissant de lui donner ce nom, car il va contenir la liste des motifs de fichier_1 à reconnaitre dans fichier_2.

Voici ce que fait mon code :

  • je stocke donc tout d'abord les motifs à reconnaitre (les lignes de fichier_1) dans le tableau nommé patterns, et le nombre de lignes de fichiers_1 dans la variable n :

    FILENAME==ARGV[1]{n=FNR; patterns[FNR]=$0}
  • puis, je stocke les lignes de fichier_2 (en les reformatant un peu) dans un tableau nommé lines, et le nombre de lignes de fichiers_2 dans la variable m :

    FILENAME==ARGV[2]{m=FNR; OFS="\t"; $(NF+1)=""; lines[FNR]=$0}
  • ensuite, je parcours le tableau des motifs, et pour chacun d'entre eux, je parcours le tableau des lignes de fichier_2 pour trouver des correspondances, et je fais l'affichage demandé :

    END{
      for (i=1;i<=n;i++){
        to_print=1
        for (j=1;j<=m;j++){
          if (lines[j] ~ "^"patterns[i]){
            if (to_print){printf("%s\t",patterns[i]); to_print=0}
            else printf("%s","\t\t")
            printf("%s\n",lines[j])
          }
        }
      }
    }

Comme dit plus haut, il y a sans doute plus économe qu'une double boucle, mais bon, étant donné l'ordre demandé, c'est simple et ça marche.
Dans ton code par contre, une fois que tu as bouclé pour récupérer le contenu de fichier_1.txt dans le tableau var, il te manque une boucle sur le contenu de fichier_2.txt pour la reconnaissance de motifs, car tu ne vas pas pouvoir te contenter d'un seul passage.
Par ailleurs, pourquoi utiliser getline, plutôt que de laisser awk parcourir ses fichiers d'entrée de lui-même ?

Hors ligne

#7 Le 23/03/2020, à 22:23

Watael

Re : AWK_utilliisation de getline et jointure

en général, pour distinguer deux fichiers lus séquentiellement, on utilise NR et FNR, ce dernier étant réinitialisé pour chaque fichier.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#8 Le 23/03/2020, à 23:29

kamaris

Re : AWK_utilliisation de getline et jointure

Oui, c'est vrai, comme cela a d'ailleurs été fait ici : https://www.developpez.net/forums/d2058 … st11437732

Dernière modification par kamaris (Le 23/03/2020, à 23:30)

Hors ligne

#9 Le 24/03/2020, à 00:13

Watael

Re : AWK_utilliisation de getline et jointure

toutafé. smile


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#10 Le 24/03/2020, à 00:40

judkil

Re : AWK_utilliisation de getline et jointure

Je comprends beaucoup mieux ! Merci beaucoup pour ces explications !

Hors ligne