IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

script a optimiser


Sujet :

Shell et commandes GNU

  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mai 2006
    Messages
    350
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2006
    Messages : 350
    Par défaut script a optimiser
    Bonjours,

    je me suis fait un script qui indente un fichier de log (celui en cour, 11635 ligne).

    Mon soucis est qu'il met un peut 4-5 seconde pour 100 ligne donc les 10 minutes pour le traitement.
    En gros, il insère une chaine donnée N fois à un endroit précis.
    exemple de chaine "| "
    exemple de log
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    2009/02/04 16:45:02:842  (t@9) BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) texte
    2009/02/04 16:45:02:842  (t@9) BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) texte
    2009/02/04 16:45:02:842  (t@9) END texte
    2009/02/04 16:45:02:842  (t@9) texte
    2009/02/04 16:45:02:842  (t@9) END texte
    Exemple de résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    2009/02/04 16:45:02:842  (t@9) BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) |  BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) |  |  texte
    2009/02/04 16:45:02:842  (t@9) |  |  BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) |  |  |  texte
    2009/02/04 16:45:02:842  (t@9) |  |  END texte
    2009/02/04 16:45:02:842  (t@9) |  |  texte
    2009/02/04 16:45:02:842  (t@9) |  END texte
    Mon script
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    more ~/Tools/indentLog.sh 
    #!/bin/bash
     
    N=`wc ~/Logs/$1/$1_current.log | awk '{print $1}'`
     
    sep="|  "
    > ~/Logs/$1/$1_current_ind.log
     
    tab0="  #  "
    tabs="$tab0"
    (( n = 0 ))
    cat ~/Logs/$1/$1_current.log | while read linein
    do
            printf "\r> $n/$N  "
     
            end=`echo $linein | grep "END"`
            if test -n "$end"
            then
                    tabs=`echo "$tabs" | sed "s/$sep//"`
            fi
     
     
            lineout=`echo $linein | sed "s/)/)$tabs/"`
            echo -e $lineout >> ~/Logs/$1/$1_current_ind.log
     
     
            begin=`echo $linein | grep "BEGIN"`
            if test -n "$begin"
            then
                    tabs=`echo "$tabs" | sed "s/$tab0/$tab0$sep/"`
            fi
     
            (( n = $n + 1 ))
    done
     
    echo " Done"
    Une amélioration par 10 serait bien venu, mais une amélioration de façon générale aussi ^^

  2. #2
    Membre émérite
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Par défaut
    Passe en langage plus évolué / plus performant, par exemple perl (ça évitera de créer 10 process pour analyser chaque ligne)... C'est certes un investissement au départ, mais très rentable.
    Sinon, j'avoue je n'ai pas regardé en détail le code (mais trop de process créés pour ce que tu veux faire à mon avis)

  3. #3
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 642
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 642
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #!/bin/bash
     
    N=$(wc -l <~/Logs/$1/$1_current.log)
    sep="|  "
    tab0="  #  "
    tabs="$tab0"
    n=1
     
    > ~/Logs/$1/$1_current_ind.log
     
    while read linein; do
            printf "\r> $n/$N  "
     
            [ -n "$(grep END <<<$linein)" ] && tabs="${tabs/$sep/}"
     
            echo "${linein/) /)$tabs}" >>~/Logs/$1/$1_current_ind.log
     
            [ -n "$(grep BEGIN <<<$linein)" ] && tabs="${tabs/$tab0/$tab0$sep}"
     
            (( n +=1 ))
     
    done <~/Logs/$1/$1_current.log
     
    echo " Done"
    Code qui retourne : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    test/croc14.sh; cat ~/Logs/$1/$1_current_ind.log
    > 7/7   Done
    2009/02/04 16:45:02:842  (t@9)  #  BEGIN  texte
    2009/02/04 16:45:02:842  (t@9)  #  |  texte
    2009/02/04 16:45:02:842  (t@9)  #  |  BEGIN  texte
    2009/02/04 16:45:02:842  (t@9)  #  |  |  texte
    2009/02/04 16:45:02:842  (t@9)  #  |  END texte
    2009/02/04 16:45:02:842  (t@9)  #  |  texte
    2009/02/04 16:45:02:842  (t@9)  #  END texte
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  4. #4
    Modérateur
    Avatar de ggnore
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    2 472
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 2 472
    Par défaut
    Aussi optimisé soit il, un script bash ne sera jamais aussi rapide que du perl ou que du langage C.
    Si tu veux faire du traitement de fichier, change de langage. S'il en existe autant, c'est bien parce qu'il répondent à des besoin différents.

    D[r]eadLock+1 en somme
    Toutes les vertus des hommes se perdent dans l’intérêt comme les fleuves se perdent dans la mer.
    N'oubliez pas de consulter les FAQ Linux et les cours et tutoriels Linux

  5. #5
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    Script sed (sous Freebsd, je pense que c'est portable) écrit en quelques secondes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     cat in
    2009/02/04 16:45:02:842  (t@9) BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) texte
    2009/02/04 16:45:02:842  (t@9) BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) texte
    2009/02/04 16:45:02:842  (t@9) END texte
    2009/02/04 16:45:02:842  (t@9) texte
    2009/02/04 16:45:02:842  (t@9) END texte
     
    $ cat a.sed tmp
    /END/{ x; s/^...//; x; }
    G
    s/)\(.*\)\n\(.*\)/)\2\1/
    /BEGIN/{ x; s/^/ | /; x; }
     
    $ sed -f a.sed in
    2009/02/04 16:45:02:842  (t@9) BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) |  texte
    2009/02/04 16:45:02:842  (t@9) |  BEGIN  texte
    2009/02/04 16:45:02:842  (t@9) |  |  texte
    2009/02/04 16:45:02:842  (t@9) |  END texte
    2009/02/04 16:45:02:842  (t@9) |  texte
    2009/02/04 16:45:02:842  (t@9) END texte
    Dis-moi ce que ça donne au niveau des performances (au moins, il n'y a pas 50 forks).

    (pour comprendre le script : man sed ou pose tes questions)

  6. #6
    Membre éclairé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mai 2006
    Messages
    350
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2006
    Messages : 350
    Par défaut
    6'45 au lieu de 9'45 pour mon fichier de 11635 ligne

    Ya donc un mieux ^^

    SI quelqu'un voit encore une optimisation a faire !! N'hésitez pas.

    Merci.

    LLB, je teste ta solution.

  7. #7
    Membre éclairé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mai 2006
    Messages
    350
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2006
    Messages : 350
    Par défaut
    LLB, ta solution est achement rapide !!

    Comment il faut le rediger pour l'avoir dans un seul script.
    Et pourrait tu décrire ce que cela signifie, pour pas que je reste comme une poire !!
    Même après avoir tenté plein de tuto, seb j'ai vraiement du mal, principalement dans la possibilité de syntaxe qui reste peut détaillé.

    encore merci.

  8. #8
    LLB
    LLB est déconnecté
    Membre émérite
    Inscrit en
    Mars 2002
    Messages
    968
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 968
    Par défaut
    Dans un script shell, tu peux mettre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    < input sed '
    /END/{ x; s/^...//; x; }
    G
    s/)\(.*\)\n\(.*\)/)\2\1/
    /BEGIN/{ x; s/^/ | /; x; }'

    Sed possède deux buffers : le premier contient la ligne courante (celle qui est à traiter), le deuxième sert à sauvegarder des informations (ici, le séparateur à insérer). La commande 'x' sert à inverser les deux buffers (car les commandes fonctionnent sur le premier).


    Ligne 1 : quand on voit "END", on supprime les trois premiers caractères du buffer de sauvegarde.

    Ligne 2 : on ajoute le buffer de sauvegarde à la fin du buffer courant (séparé par un retour à la ligne). On obtient par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    2009/02/04 16:45:02:842  (t@9) texte
     |  |
    Ligne 3 : on sélectionne "texte" (entre la parenthèse et le retour à la ligne) et le séparateur. On les remet dans l'ordre. On obtient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    2009/02/04 16:45:02:842  (t@9) |  |  texte
    Ligne 4 : quand on voit "BEGIN", on ajoute " | " au début du buffer de sauvegarde.


    Sed est un outil excellent, permettant de réaliser des tâches complexes en très peu de lignes. Mais, ça prend 10 fois plus de temps à expliquer ce que fait le script qu'à l'écrire.

  9. #9
    Membre éclairé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mai 2006
    Messages
    350
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2006
    Messages : 350
    Par défaut
    Bon ben j'ai compris, mais, c'est d'un tendu a écrire !!
    Mais je pense que cela m'aidera pour en faire d'autre prochainement.

    Merci pour la rapidité de réponse, a tout ceux qui ont participé.
    Et le chalenge est bien entendu relevé puisque le script met même pas 2 seconde a faire les 11000 ligne !!

  10. #10
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bonsoir.

    J'arrive après la bataille me semble-t-il. Je mets tout de même une solution à base de awk, qui sera certainement plus lente, mais qui marche et qui est, selon moi, plus lisible.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    awk '
    {
      printf "%s %s %s%s", $1, $2, $3, level
      for (field = 4; field <= NF; field++) {printf " %s", $field}
      if ($4 ~ /^BEGIN$/) {level = level " |"}
      else if ($4 ~ /^END$/) {level = substr(level, 0, length(level) - 2)}
      print ""
    }' file_in > file_out

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] Optimisation de scripts PHP/MySQL
    Par DgG dans le forum PHP & Base de données
    Réponses: 368
    Dernier message: 20/11/2013, 18h59
  2. Script demande optimisation
    Par BUENOO dans le forum Général Python
    Réponses: 42
    Dernier message: 29/02/2012, 18h02
  3. Optimiser vos scripts
    Par djibril dans le forum Langage
    Réponses: 33
    Dernier message: 11/06/2009, 16h10
  4. [Débutant] Accélérer et optimiser ses scripts PHP
    Par Metallic-84s dans le forum Langage
    Réponses: 6
    Dernier message: 24/03/2006, 12h37
  5. [MySQL] [Script]Optimisation de scripts Php/MySQL (2)
    Par copy dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 27/08/2004, 08h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo