Exo en bash ^^ - Shell/Batch - Programmation
Marsh Posté le 20-04-2010 à 23:57:18
si tu peux, c'est plus rapide de passer par awk
Marsh Posté le 21-04-2010 à 19:17:03
Analyse un peu ce code...
Code :
|
art_dupond a écrit : si tu peux, c'est plus rapide de passer par awk |
Attention aux affirmations gratuites. awk est peut-être plus souple à programmer mais le programme awk étant très massif, il est assez lourd à se charger...
Marsh Posté le 21-04-2010 à 21:10:31
Merci beaucoup, je l'ai introduit dans mon code et ça fonctionne, ça va légèrement plus vite que mon premier code . Le prof nous avait dit que sans la commande "sed" ce n'était pas possible de résoudre l'exercice preuve que non ^^
J'aimerai juste savoir exactement ce que veut dire =>> $( grep ":varmatiere:" result) pour être bien sûr de bien comprendre ^^
Moi je le traduit comme ça : pour chaque ligne le programme va rechercher où "math" apparaît dans le fichier result et si on fait un echo $ligne il va afficher chaque ligne qui contient ce champ "math", ai-je raison ? ^^
Et de là j'ai pu faire mes tests pour prendre que les champs qui m'intéresse et ainsi afficher que les étudiant en échec avec leurs points ^^
Marsh Posté le 22-04-2010 à 09:32:07
Sve@r a écrit :
|
C'était pas gratuit, j'ai tested avant
sur un "gros" fichier (2M entrées) :
Maintenant, pour l'exercice, sans doute que ça change pas grand chose. Mais ça pourrait toujours servir de savoir que awk pourrait être une alternative intéressante
edit: mmm... mais pit-être aussi que c'était le sed qui ralentissait le truc. retest ce soir
Marsh Posté le 22-04-2010 à 14:20:44
art_dupond a écrit :
|
J'ai pas testé sans le SED, mais je me suis demandé aussi si ce n'était pas lui qui ralentissait le truc, faudra que je test ce soir. Pour awk je ne le connais pas bien, le prof ne l'a pas mentionné, donc je vai comparer les deux codes, mon 2ème avec le grep et un avec awk ^^ Maintenant c'est sûr mon fichier result est tout petit donc ca change pas grand chose, mais le souci c'est que le prof n'en tient pas compte, il veut un truc performant
Marsh Posté le 22-04-2010 à 19:29:22
Hello87 a écrit : Merci beaucoup, je l'ai introduit dans mon code et ça fonctionne, ça va légèrement plus vite que mon premier code . Le prof nous avait dit que sans la commande "sed" ce n'était pas possible de résoudre l'exercice preuve que non ^^ |
grep xxx => extraction de toutes les lignes contenant le motif "xxx". Ca t'évite de te palucher la recherche à la mano. Ainsi ta boucle while ne contient que les gars avec matière "math". Toutefois, si un gars se prénomme "math", il apparaitra aussi. Désolé, j'ai pas d'idée pour demander à grep de ne chercher la matière que dans le 3° champ. J'ai bien une solution en filtrant le fichier input à base de cut mais ça implique de perdre des infos utiles par la suite. Ou alors voir la solution de art_dupond à base de awk. C'est pas forcément une mauvaise idée toutefois on sort du cadre strict du shell...
art_dupond a écrit :
|
Je comprends ton point de vue. Moi aussi j'ai eu des scripts en shell qui parsaient de gros fichiers et qui mettaient plus d'1h pour s'exécuter alors que d'autres langages plus rapides (comme awk, ou python) me traitaient ça en qq secondes. Toutefois ton affirmation initiale ne faisait pas état de la grosseur du fichier à traiter. Or c'est une caractéristique importante dans la décision de l'outil à utiliser...
Hello87 a écrit : J'ai pas testé sans le SED, mais je me suis demandé aussi si ce n'était pas lui qui ralentissait le truc, faudra que je test ce soir. |
Absolument pas. sed est un outils de traitement d'un flot de lignes des plus rapides qui soient.
Hello87 a écrit : Maintenant c'est sûr mon fichier result est tout petit donc ca change pas grand chose, mais le souci c'est que le prof n'en tient pas compte, il veut un truc performant |
Alors si le langage n'a pas d'importance et que tu veux un truc performant, essaye ceci
Code :
|
Marsh Posté le 22-04-2010 à 20:43:31
Sve@r a écrit : |
Parce qu'on s'en fout de la différence dans le cas d'un pitit fichier
Spoiler : De toute façon awk gagne quand même |
En fait c'est la lecture du fichier avec le for (ou while) qui est super super lente (je sens que je vais modifier quelques uns de mes scripts moi )
Marsh Posté le 23-04-2010 à 23:54:21
art_dupond a écrit : De toute façon awk gagne quand même :o |
Pas toujours. Je viens de le voir sur un test simple. Mais il gagnera si on le compare à un enchainement de pipes...
Test1: un simple grep comparé avec un awk
Citation : prompt_$>time grep "^root:" /etc/passwd |
Là, le awk est nettement plus long
Test2: le grep est transformé pour modifier les infos
Citation : prompt_$>time cat /etc/passwd |grep "^root:" /etc/passwd |sed -e "s/^root:/admin:/" |
Là il gagne...
Marsh Posté le 24-04-2010 à 06:27:49
Forcément si tu changes l'énonce...
Marsh Posté le 24-04-2010 à 09:22:15
art_dupond a écrit : Forcément si tu changes l'énonce... |
Bah ??? J'ai rien changé. On parlait des différences de performances à utiliser le awk pour traiter du fichier. J'ai donné un exemple où je compare awk avec d'autres outils et où je traite un petit fichier. Et en plus tu devrais être content puisque mon second exemple montre que tu avais raison et que si on doit faire un gros traitement en enchainant diverses commandes pipées, vaudra alors mieux lui préférer un programme unique awk contenant le traitement complet...
Marsh Posté le 24-04-2010 à 17:36:49
Sve@r a écrit : |
Non mais faut pas faire attention, c'es juste que j'aime les dialogues de sourds
Sinon pour l'exo, c'est toi qui avais raison finalement
Code :
|
25% plus rapide que awk sur mon gros gros fichier
Enfin ça va aussi dépendre du traitement final après ça et du nombre d'échecs pour ce traitemet
En tout cas, j'aurai appris qu'il faut éviter de parcourir un fichier avec un for si c'est possible
Marsh Posté le 30-04-2010 à 00:21:04
Dites, puisqu'on en est à parler de perfs entre awk et bash, je voudrais poser une pitite question.
Y-a-t-il une différence de perf entre
Citation : |
Marsh Posté le 30-04-2010 à 01:49:03
oui ça bien sur, mais en fait j'ai mal posé ma question, je me demandais s'il y a une différence de comportement entre fait le test dans le { } ou avant.
Il y a effectivement une différence de temps d'exécution, la première etant plus lente.
Mais je me demande pourquoi.
Marsh Posté le 07-05-2010 à 17:22:04
En fait ça ressemble un peu au principe du grep : quand tu mets un tests dans l'accolade il va faire plus d'opérations avant de se rendre compte que le tests est faux et ne pas imprimer que lorsqu'il effectue une comparaison avant les accolade.
De façon générale sous Unix :
accolade = fork un fils pour accomplir ce qu'il y a dedans.
Pas d'accolade = pas de fork, donc gain de temps sur des opérations aussi simples.
enfin là on est dans le fonctionnement intrinsèque du AWK = je peux sans doute me planter, à valider donc avec un expert (en évitant les vérités toutes prêtes please! )
Marsh Posté le 08-05-2010 à 01:13:50
Kerrozen a écrit : En fait ça ressemble un peu au principe du grep : quand tu mets un tests dans l'accolade il va faire plus d'opérations avant de se rendre compte que le tests est faux et ne pas imprimer que lorsqu'il effectue une comparaison avant les accolade. |
Je vois pas trop où il y a des accolades dans un grep. Toutefois, ta remarque sur le test faux qui se continue quand-même me fait me rappeler qu'en shell, si un test "and" commence par être faux, même s'il est définitivement faux, le test se poursuit quand-même jusqu'à la fin.
Exemple
Code :
|
Le test a = b étant faux, l'ensemble complet est faux et on voit bien arriver "bad". Toutefois, le fichier "toto" est quand-même créé preuve que le test a (bien inutilement) analysé la seconde évaluation.
On peut aussi voir de façon analogue qu'un test "or" commençant par une évaluation vraie se poursuivra quand-même jusqu'à la fin.
Kerrozen a écrit : De façon générale sous Unix : |
Tu veux sans doute parler de parenthèses car les accolades en shell ont une autre signification. Cependant les parenthèses, si elles ont pour effet de permettre le regroupement de commandes, ne génèrent pas de sous-processus (ou alors il est invisible)
Exemple
Code :
|
L'exécution de ce script me donne un état des processus identique dans les deux cas. Cependant, la variable "a" modifiée dans les parenthèses reste inchangée une fois celles-ci refermées. Je sais pas si on peut appeler ça "sous-processus" bien que ça s'en rapproche terriblement...
Kerrozen a écrit : enfin là on est dans le fonctionnement intrinsèque du AWK = je peux sans doute me planter, à valider donc avec un expert (en évitant les vérités toutes prêtes please! ) |
Exact. Dans le awk (qui est un programme indépendant mais ne générant qu'un seul processus), les accolades indiquent le début et fin de l'algo. Toutefois peut-être que mettre directement un code simple sans accolade le fait aller plus vite j'en sais trop rien. Mais même si c'est le cas, ce n'est pas dû à un processus en plus ou en moins. Ce sera dû uniquement à une analyse un peu plus simple donc plus rapide...
Marsh Posté le 10-05-2010 à 11:42:48
Sve@r a écrit :
|
Bon alors, excusez-moi des mes propos diffus dignes d'un bafouilleur professionnel
On n'est bien d'accord qu'il n'est pas question de parenthèse / accolade dans le grep qui fait très bien son travail tout seul
Pour rentrer dans le détail, l'utilisation des parenthèses implique bien la création d'un sous-shell qui est invisible pour le reste (donc fork d'un processus fils par le processus en court). La portée est limitée à son propre contexte : toutes les variables utilisées ne sont pas gardées en mémoire une fois la parenthèse fermée, et on n'a pas accès aux variables du processus père à l'intérieur des parenthèses : pour revenir à l'exemple de Sve@r, le 'a' à l'intérieur de la parenthèse n'est en fait pas le même que celui du dehors.
Quant aux accolades, elles ne font que définir une fonction sans nom, un bloc de commandes en particulier : leur portée reste à l'intérieure du processus en court :
Code :
|
Pour plus d'information, voici un cours assez bien fait qui passe sur le sujet.
Pour revenir à la dernière question, à savoir pourquoi AWK plus rapide avec test dehors plutôt que dedans les accolades
Concernant le AWK, Sve@r nous illumine encore puisqu'effectivement le système reste celui des accolades, donc de la fonction sans nom (qu'il désigne par algo). Lorsque qu'on met un test à l'intéreur des accolades, non seulement il va analyser tout le bloc à la recherche d'une suite éventuelle au test, qu'il soit faux ou non, mais en plus il va le faire pour chaque ligne en entrée.
Mettre le test en dehors des accolades permet de zapper tout le bloc d'un coup lorsque le test est faux et de ne traiter que les lignes concernées => gain de temps non négligeable sur une forte volumétrie. (au passage : d'où l'intérêt de bien connaître la bête AWK pour la rendre encore plus performante ^^)
Voilà voilà, encore désolé pour mes petites cafouilleries
Marsh Posté le 20-04-2010 à 19:18:07
Bonjour
Notre prof nous a demandé d'afficher les noms et les pourcentages des étudiants en échec en math à partir du fichier result que voici :
Dupond:Pierre:math:45:100
Latour:Amandine:math:42:100
Riri:Patrick:math:36:100
mathieu:Jack:geo:38:100
##=>> j'ai mis exprès mathieu pour "math"(comme ça quand je vais faire la recherche dans ce fichier avec le grep je devrai faire attention à ça) et comme matière j'ai rajouté geo au lieu de math car le prof nous la demandé pour compliqué les choses ^^
Voici comment je l'ai résolu :
#!bin/bash
echo " Quelle matière voulez-vous voir ? "
read varmatiere
for ligne in $(sed 's/ /g' result)
do
if [ `echo $ligne | cut -d: -f3 = $varmatiere` ]
then
if [ `echo $ligne | cut -d: -f4` -lt 50 ]
then
echo " `echo $ligne | cut -d: -f1,4` "
cpt=$((cpt + 1))
fi
fi
done
Le souci c'est qu'il va chaque fois tester si chaque champs ( -f3 ) correspond bien à varmatiere et par conséquent cela met du temps.
Le prof m'a suggérer d'utiliser un grep comme ceci : search=`grep -w $varmatiere result`, seulement je ne vois pas comment l'intégrer dans mon script. Je pensais faire comme ceci :
#!bin/bash
echo " Quelle matière voulez-vous voir ? "
read varmatiere
search=`grep -w $varmatiere result`
#Mais ensuite comment l'intégrer dans ma boucle for pour qu'il l'accepte ? De plus le grep est-il vraiment la meilleur solution pour que ce soit plus efficace ?
for ligne in $(sed 's/ /g' result)
do
if [ `echo $ligne | cut -d: -f3 = $varmatiere` ] # le -f3 c'est le champs qui corresponds à la matière
then
if [ `echo $ligne | cut -d: -f4` -lt 50 ] # le -f4 aux points
then
echo " `echo $ligne | cut -d: -f1,4` " # et le -f1 au nom de l'étudiant
cpt=$((cpt + 1)) #Un petit compteur à la fin pour me dire le nombre d'échec en tout ^^
fi
fi
done
Voilà je remercie d'avance ceux qui ont lu mon message jusqu'au bout , je ne sais pas si c'est bien clair tout ce que j'ai mis, mais j'attends vos suggestions et n'hésitez à me dire si il y a des erreurs
Message édité par Hello87 le 21-04-2010 à 18:20:17