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 08/10/2015, à 21: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.8

Pierre Petit
Français : 12
Math : 17
Physique : 17
Informatique : 14
Sport :15
Moyenne : 15

Pierre Caillou
Français : 12
Math : 17
Physique : 17
Informatique : 14
Sport :15
Moyenne : 15

Toto
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, à 23:36)

#2 Le 08/10/2015, à 22: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, à 22:31

Compte supprimé

Re : Awk traitement par section

Bonsoir pingouinux smile

Merci pour ta solution qui marche parfaitement ! cool

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 ? roll )

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, à 23:15)

#4 Le 09/10/2015, à 07: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, à 08:28)

Hors ligne

#5 Le 10/10/2015, à 00: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. wink

#6 Le 10/10/2015, à 23: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 ! roll

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 11/10/2015, à 00:27)

#7 Le 11/10/2015, à 07: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, à 07:19)

Hors ligne

#8 Le 11/10/2015, à 11: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, à 11:54)

#9 Le 11/10/2015, à 13: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, à 13: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, à 13:39)

#11 Le 11/10/2015, à 14: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, à 14:15

Compte supprimé

Re : Awk traitement par section

pingouinux a écrit :

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. roll

Dernière modification par Compte supprimé (Le 11/10/2015, à 14:16)

#13 Le 11/10/2015, à 17: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 ! cool

Dernière modification par Compte supprimé (Le 11/10/2015, à 17:20)

#14 Le 11/10/2015, à 18: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, à 19:13

Compte supprimé

Re : Awk traitement par section

Tes 2 derniers scripts sont magnifique ! cool

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, à 19: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, à 11:33)

Hors ligne