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