Pages : 1
#1 Le 08/10/2015, à 20:21
- Compte supprimé
Awk traitement par section
Bonjour,
Voilà un fichier contenant ça:
Louis Dubois
Français : 13
Math : 15
Physique : 12
Informatique : 20
Sport :14
Moyenne : 14.8Pierre Petit
Français : 12
Math : 17
Physique : 17
Informatique : 14
Sport :15
Moyenne : 15Pierre Caillou
Français : 12
Math : 17
Physique : 17
Informatique : 14
Sport :15
Moyenne : 15Toto
Français : 0
Math : 0
Physique : 0
Informatique : 0
Sport : 20
Moyenne : 4
Remarque : non promu
J'aimais traiter ce fichier en utilisant awk afin d'obtenir les noms des élèves et leurs moyennes.
Pour arriver à ce résultat:
Louis Dubois : 14.8
Pierre Petit : 15
Pierre Caillou : 15
Toto : 4
Dans mon exemple j'ai utilisé que 4 élèves mais en réalité j'aimerais faire cet exercice pour une école de 2000 élèves... disons que c'est pour le principe.
Dernière modification par Compte supprimé (Le 10/10/2015, à 22:36)
#2 Le 08/10/2015, à 21:17
- pingouinux
Re : Awk traitement par section
Bonsoir,
awk '!/[0-9]/{s=$0} /Moyenne :/{s=s": "$3;print s}' fichier
Hors ligne
#3 Le 08/10/2015, à 21:31
- Compte supprimé
Re : Awk traitement par section
Bonsoir pingouinux
Merci pour ta solution qui marche parfaitement !
Mais tu peux m'expliquer un peu ton code...
Edit:
J'avais commençé ce script mais il ne fonctionnait pas, j'ai l’impression que le problème viens de mon END qui retiens la dernière variable "nom" et "moyenne". (je comprends pas ce qui ce passe en fait ? )
awk 'BEGIN {
FS=":";
}
!/[0-9]/{
nom=$0}
/Moyenne/{
moyenne=$2;}
END {
printf "%s : %s\n " ,nom,moyenne
}' fichier
Retourne:
Remarque : non promu : 4
Dernière modification par Compte supprimé (Le 08/10/2015, à 22:15)
#4 Le 09/10/2015, à 06:07
- pingouinux
Re : Awk traitement par section
C'est parce qu'il ne faut pas imprimer à la fin, mais lorsque tu lis chaque moyenne.
Voici ton script légèrement modifié
awk '
BEGIN{FS=":"}
!/[0-9]/ {nom=$0}
/Moyenne/ {moyenne=$2;printf "%-18s : %4.1f\n" ,nom,moyenne}
' fichier
et le résultat
Louis Dubois : 14.8
Pierre Petit : 15.0
Pierre Caillou : 15.0
Toto : 4.0
Ajouté : Vérifie que la moyenne de Dubois apparaît correctement (normalement oui)
Dernière modification par pingouinux (Le 09/10/2015, à 07:28)
Hors ligne
#5 Le 09/10/2015, à 23:43
- Compte supprimé
Re : Awk traitement par section
Merci pingouinux !
Je confirme... ça fonctionne !
Et aussi merci pour ta réponse concernant le "END" maintenant, je comprends mieux son fonctionnement.
#6 Le 10/10/2015, à 22:39
- Compte supprimé
Re : Awk traitement par section
Maintenant je cherche comment faire pour avoir seulement les moyennes de Louis Dubois, Pierre Caillou et la note de sport de Toto qui est de 20 ?
Pour avoir ce résultat:
Louis Dubois : 14.8
Pierre Caillou : 15.0
Toto : 20
Et là pour moi ça se complique vraiment !
J'ai pensé utiliser une boucle while, du style si le nom n'est pas Pierre Petit ... imprime le nom et la moyenne et si le nom est Toto imprime la note de sport.
Dernière modification par Compte supprimé (Le 10/10/2015, à 23:27)
#7 Le 11/10/2015, à 06:07
- pingouinux
Re : Awk traitement par section
Voilà !
awk '
BEGIN{FS=":"}
!/[0-9]/ {nom=$0}
/Moyenne/ {if(nom~/Louis Dubois|Pierre Caillou/) printf "%-18s : %4.1f\n" ,nom,$2}
/Sport/ {if(nom~/Toto/) printf "%-18s : %4.1f\n" ,nom,$2}
' fichier
Résultat
Louis Dubois : 14.8
Pierre Caillou : 15.0
Toto : 20.0
Édité :
Moins lisible, mais plus propre (autorise un nombre quelconque d'espaces entre le prénom et le nom, et s'assure que ces derniers sont des mots entiers : ne pas tenir compte de Totobis, par exemple)
" +" : une ou plusieurs espaces
"\<" :a début de mot
"\>" : fin de mot
awk '
BEGIN{FS=":"}
!/[0-9]/ {nom=$0}
/Moyenne/ {if(nom~/\<(Louis +Dubois|Pierre +Caillou)\>/) printf "%-18s : %4.1f\n" ,nom,$2}
/Sport/ {if(nom~/\<Toto\>/) printf "%-18s : %4.1f\n" ,nom,$2}
' fichier
Dernière modification par pingouinux (Le 11/10/2015, à 06:19)
Hors ligne
#8 Le 11/10/2015, à 10:50
- Compte supprimé
Re : Awk traitement par section
Merci, ça parait si simple...
Si tu as encore un peu de temps pour moi (je sais j'abuse...)
Comment faire pour avoir ce résultat:
Louis Dubois
Français : 13
Math : 15
Toto
Sport : 20
Voici le code que j'ai trouvé en m'inspirant des solutions déjà données dans ce topic.
awk '
BEGIN{FS=":"}
!/[0-9]/ {nom=$0}
/Français/ {
if (nom~/Louis Dubois/)
printf "%s\n Français : %4.1f\n" ,nom,$2;
}
/Math/ {
if (nom~/Louis Dubois/)
printf " Math : %4.1f\n" ,$2;
}
/Sport/ {
if (nom~/Toto/)
printf "\n%s\n Sport : %4.1f\n" ,nom,$2;
}
' fichier
ça marche, mais je pense qu'on peut le simplifié mais là je bloque
Dernière modification par Compte supprimé (Le 11/10/2015, à 10:54)
#9 Le 11/10/2015, à 12:16
- pingouinux
Re : Awk traitement par section
Je ferais comme ceci (il n'y a alors pas besoin de connaître l'ordre des matières dans le fichier)
awk '
BEGIN{FS=":"}
!/[0-9]/ {if(s) printf("%s\n%s\n",nom,s);nom=$0;s=""}
{
if (nom~/Louis Dubois/) {
if($1~/Français|Math/) s=s""sprintf("%-13s : %4.1f\n",$1,$2)
}
if (nom~/Toto/) {
if($1~/Sport/) s=s""sprintf("%-13s : %4.1f\n",$1,$2)
}
}
END{if(s) printf("%s\n%s\n",nom,s)}
' fichier
Hors ligne
#10 Le 11/10/2015, à 12:35
- Compte supprimé
Re : Awk traitement par section
Sinon je pense à un truc du genre
awk '
BEGIN{FS=":"}
!/[0-9]/ {nom=$0}
si nom = Louis Dubois
Recherche la ligne Math
mémorise $2 dans la viriable ma
Recherche la ligne Français
mémorise $2 dans la variale fr
Imprime "Louis Dubois Math: Français:" ,nom,ma,fr
' fichier
Edit: oups, je n'avais pas vu que tu avais déjà répondu, merci encore !
A part ça je vais quand même essayer avec des variables (je suis têtu) mais je ne suis pas sorti de l'auberge, je ne métisse pas encore bien le placement des accolades, des parenthèses et surtout la structure de ce merveilleux outil qu'est awk !
Dernière modification par Compte supprimé (Le 11/10/2015, à 12:39)
#11 Le 11/10/2015, à 13:11
- pingouinux
Re : Awk traitement par section
Ce que j'ai fait en #9 ressemble un peu à ce que tu proposes en #10, mais je n'utilise pas de variable spécifique. Pour un élève donné, les résultats des différentes matières qui nous intéressent sont stockés dans la variable s. Cette variable est imprimée quand on change d'élève, qu'on lit une ligne vide, ou à la fin du programme.
Hors ligne
#12 Le 11/10/2015, à 13:15
- Compte supprimé
Re : Awk traitement par section
Ce que j'ai fait en #9 ressemble un peu à ce que tu proposes en #10, mais je n'utilise pas de variable spécifique. Pour un élève donné, les résultats des différentes matières qui nous intéressent sont stockés dans la variable s. Cette variable est imprimée quand on change d'élève, qu'on lit une ligne vide, ou à la fin du programme.
Ok, il faut alors que je médite sur ton code #9, morceau par morceau car des éléments et le fonctionnement m'échappe encore pour le moment.
Dernière modification par Compte supprimé (Le 11/10/2015, à 13:16)
#13 Le 11/10/2015, à 16:18
- Compte supprimé
Re : Awk traitement par section
J'ai trouvé une soluce (moche) avec les variables:
awk '
BEGIN{FS=":"}
!/[0-9]/ {nom=$0}
nom~/Louis Dubois/ && /Français/ {ldFrancais=$0;}
nom~/Louis Dubois/ && /Math/ {ldMath=$0;}
nom~/Toto/ && /Sport/ {totoSport=$0;}
END {printf "Louis Dubois\n%s\n%s\n\nToto\n%s\n" ,ldFrancais,ldMath,totoSport}
'fichier
Mais ta solution #9 est plus classe !
Dernière modification par Compte supprimé (Le 11/10/2015, à 16:20)
#14 Le 11/10/2015, à 17:06
- pingouinux
Re : Awk traitement par section
En reprenant #9, on peut simplifier un peu
awk '
function mon_print() {if(s) printf("%s\n%s\n",nom,s);nom=$0;s=""}
function add_resul() {s=s""sprintf("%-13s : %4.1f\n",$1,$2) }
BEGIN{FS=":"}
!/[0-9]/ {mon_print();nom=$0;s=""}
nom~/Louis Dubois/ && /Français|Math/ {add_resul()}
nom~/Toto/ && /Sport/ {add_resul()}
END{if(s) mon_print()}
' fichier
Hors ligne
#15 Le 11/10/2015, à 18:13
- Compte supprimé
Re : Awk traitement par section
Tes 2 derniers scripts sont magnifique !
Mais là je suis vraiment largué, si tu peux m'expliquer un peu le principe ça serai cool de ta part.
Comme par exemple:
!/[0-9]/ {if(s) printf("%s\n%s\n",nom,s);nom=$0;s=""}
je ne comprends pas if(s)
et
if($1~/Français|Math/) s=s""sprintf("%-13s : %4.1f\n",$1,$2)
je ne comprends pas le s=s""sprintf
Merci
#16 Le 11/10/2015, à 18:31
- pingouinux
Re : Awk traitement par section
if(s) commande
L'instruction qui suit le test n'est exécutée que si s est un nombre différent de zéro ou une chaîne non vide.
s=s""sprintf("%-13s : %4.1f\n",$1,$2)
sprintf retourne la chaîne qui aurait été imprimée avec printf, et on ajoute à s le résultat de la commande sprintf.
Édité : Voici une autre façon de procéder
s=sprintf("%s%-13s : %4.1f\n",s,$1,$2)
Dernière modification par pingouinux (Le 12/10/2015, à 10:33)
Hors ligne
Pages : 1