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 :

Piste d'amélioration de la vitesse d'un script


Sujet :

Shell et commandes GNU

  1. #1
    Invité
    Invité(e)
    Par défaut Piste d'amélioration de la vitesse d'un script
    Bonjour,

    C'est un peu la suite du poste ici

    Je récupère un numéro à partir du nom du fichier (du caractère 4 au 21) qui peut avoir des zéros au début (et c'est quasi toujours le cas)
    J'utilise donc la commande suivante pour le récupérer (le echo est là car je récupère le nom du fichier via une requête SQL, plus exactement une liste de fichier)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    numero=`echo "$fichier" | cut -c 4-21 | sed 's/^0*//'`
    echo $numero
    41
    Je récupère toute les lignes de 11 caractères : cela peut être de la forme "ABCD 000001" ou "ABCDE0999999"
    Je remplace l'espace par le symbole "_" pour pouvoir utiliser le résultat dans une liste.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    liste_ligne_nb_cr_type=`awk 'length == 11 { sub(/ /,"_",$0); print $0 }' output/$fichier`
    echo $liste_ligne_nb_cr_type
    AB13_000023 AB123000023
    Voici la partie à optimiser:
    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
     
          for fichier in $liste_fichier
          do
     
            #On récupére le numéro de l'abonné : ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx => 41
            numero_abonne=`echo "$fichier" | cut -c 4-21 | sed 's/^0*//'`
     
            #Ne garder que les en-tête évènement = Ligne de 11 caractères commençant par une lettre (on y remplace l'espace par "_" pour l'avoir en un seul morceau)
            liste_ligne_nb_cr_type=`awk 'length == 11 { sub(/ /,"_",$0); print $0 }' output/$fichier`
     
            for ligne_nb_cr_type in $liste_ligne_nb_cr_type
            do
              #Nombre de CR associé à ce type de cr (AB13_000023 => 23)
              nb_cr=`echo $ligne_nb_cr_type | sed 's/.....0*\(.*\)/\1/'`
              #Abonné associé à son type de CR sous la forme : AB13__41 / AB123_41 ( "type cr" _ "numéro abonné" )
              type_subscriber=`echo $ligne_nb_cr_type | sed "s/\(.....\).*/\1_$numero_abonne/"`
              #On l'ajoute à la liste des abonnés associés à leur type de CR
              liste_type_subscriber+=" $type_subscriber"
              #Cumuler le nombre de CR pour chaque type
              eval $type_subscriber=$(($type_subscriber + $nb_cr))
            done
          done
          #On trie les abonnés associés à leur type de CR (en enlevant les doublons)
          liste_type_subscriber_unique=`for type_subscriber in $liste_type_subscriber; do echo $type_subscriber; done | sort -u`
    J'avais pensé à tester si l'abonné existait déjà dans la liste "liste_type_subscriber" avant de l'ajouter. Mais il semble plus efficace de tous les ajouter puis de faire un sort à la fin.
    Je pourrais essayer de me servir du awk pour faire les calculs, mais il ne semble pas possible d'utiliser une variable externe afin de la modifier ...
    Je stocke tout en mémoire plutôt que dans des fichiers car cela devrait être plus rapide.

    Auriez-vous des idées d'optimisation ?

    Merci

    ps: le code était moins rapide avant
    Dernière modification par Invité ; 11/03/2014 à 23h08.

  2. #2
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Bonjour

    Entendre "bash" et "optimisation" dans la même phrase me fait sourire. Bash est un script pour faire facilement des tâches idiotes. Il est très lent.

    Si tu veux de l'optimisation, fais du C++ ou java. Surtout pour travailler des caractères; ce n'est pas hors de portée.

  3. #3
    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
    Tu pourrais aussi faire du perl : tu n'aurais pas à lancer des sed à gogo. C'est très adapté pour parser du texte et vraiment pas très éloigné du shell.
    Si tu veux évaluer le temps d'exécution de ton script utilise la commande time. Il te faut mesurer le temps d'exécution, plutôt que d'utiliser le conditionnel
    ça devrait aller plus vite
    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

  4. #4
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 360
    Par défaut
    Bonjour,

    En étant plus clément et en regardant rapidement, la dernière boucle for me parait inutile, et je pense même que l'on doit pouvoir faire la même chose sans toutes ces boucles.
    Tu dois pouvoir récupérer l'ensemble des informations que tu as besoin avec une seule commande sed...
    Mais bon, c'est un regard très rapide...

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par ggnore Voir le message
    Tu pourrais aussi faire du perl : tu n'aurais pas à lancer des sed à gogo. C'est très adapté pour parser du texte et vraiment pas très éloigné du shell.
    Si tu veux évaluer le temps d'exécution de ton script utilise la commande time. Il te faut mesurer le temps d'exécution, plutôt que d'utiliser le conditionnel
    Oui la commande time est bien pour tester tout cela. C'est ce que j'ai fait
    Mais comme je n'ai pas fait de tests sur l'architecture finale, je ne peux pas être sûr à 100%. La quantité de fichiers à traiter et la vitesse des disque sera différent.

    Citation Envoyé par Flodelarab Voir le message
    Bonjour

    Entendre "bash" et "optimisation" dans la même phrase me fait sourire. Bash est un script pour faire facilement des tâches idiotes. Il est très lent.

    Si tu veux de l'optimisation, fais du C++ ou java. Surtout pour travailler des caractères; ce n'est pas hors de portée.
    Je suis d'accord. Mais dans ce cas, il faut demander l'aide d'une personne connaissant java et c'est ça le problème... A mois que j’apprenne le java sur mon temps libre pour le boulot
    Enfin, si on a toujours des problèmes pour avoir la liste des fichiers à analyser, on passera peut-être au java (une autre méthode pour récupérer cette liste l'utilise)
    Bon en tout cas l'optimisation du script fonctionne bien. On passe de 20-30min à 3-6min

    Citation Envoyé par disedorgue Voir le message
    Bonjour,

    En étant plus clément et en regardant rapidement, la dernière boucle for me parait inutile, et je pense même que l'on doit pouvoir faire la même chose sans toutes ces boucles.
    Tu dois pouvoir récupérer l'ensemble des informations que tu as besoin avec une seule commande sed...
    Mais bon, c'est un regard très rapide...
    Je ne vois pas d'autre manière de supprimer les doublons d'une liste. Je suis preneur car je n'aime pas cette méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ echo $liste
    abc def ghi abc def ghi
     
    $ echo $liste | sort -u
    abc def ghi abc def ghi
    Enfin, si un coup de sed pour changer les espace par des retours chariot, mais dans ce cas ce serait plus long que la boucle for (testé avec la commande time)

    Je pense aussi comme toi qu'on doit pouvoir se passer de la boucle pour l'autre partie. Le poste suivant me donne une idée : lien
    Je vais voir ce que ça donne au final.

  6. #6
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 360
    Par défaut
    Exemple de remplacement de ta dernière boucle (il faut respecter le retour à la ligne):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ echo $liste
    abc def ghi abc def ghi abc def ghi abc def ghi
    $ sort -u - <<<"${liste// /
    }"
    abc
    def
    ghi
    Pour le reste du code, il faudrait un input et un output d'exemple sur lequel on peut travailler si tu veux que l'on t'aide à améliorer les perfs.

    PS: perso, je ne pense pas que java serait le meilleur choix si le shell ne suffisait pas, perl ou python suffirait largement

  7. #7
    Invité
    Invité(e)
    Par défaut
    Aouch, joli ton sort

    Un exemple de fichier était dans le lien du premier poste (mais bien caché)
    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 ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    INFO......................................................
    ABCD 000001
    00........................................................
    01........................................................
    05........................................................
    10........................................................
    20........................................................
    99........................................................
    EFGH 000015
    00........................................................
    01........................................................
    05........................................................
    10........................................................
    20........................................................
    99........................................................
    IJKLM000005
    00........................................................
    01........................................................
    05........................................................
    10........................................................
    20........................................................
    99........................................................
    Pouf, code ré-écrit et beaucoup plus rapide
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ parametre=toto
    $ liste_fichier="ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    $ awk 'length == 11 { type_cr=substr($0,1,5);
    nb_cr=substr($0,6,6);
    nom_fichier=FILENAME;
    sub(/.*\//,"",nom_fichier);
    numero_abonne=substr(nom_fichier,4,18)+0
    sub(/ /, "", type_cr);
    tableau[type_cr]+=nb_cr}
    END { for (id in tableau) print "xxxxxxxxxxxxxxxxxxxx;"id";"numero_abonne";"tableau[id]";'$parametre';xxxxxxxx" }' $liste_fichier
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    xxxxxxxxxxxxxxxxxxxx;ABCD;41;3;toto;xxxxxxxx
    xxxxxxxxxxxxxxxxxxxx;EFGH;41;45;toto;xxxxxxxx
    xxxxxxxxxxxxxxxxxxxx;IJKLM;41;15;toto;xxxxxxxx
    Par contre awk bug quand la variable paramètre contient un accent. Une idée pour résoudre ce problème?
    Sinon, combien de fichier peuvent être passés en paramètre à awk ?
    Dernière modification par Invité ; 13/03/2014 à 23h36.

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ecatomb Voir le message
    Sinon, combien de fichier peuvent être passés en paramètre à awk ?
    Salut

    Très exactement 174200 (sisi, j'ai fait des tests )
    Mais si t'en as plus, tu as xargs qui est fait pour découper une grande liste d'éléments en plusieurs petites afin de les transférer à une commande Unix...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Expert confirmé
    Avatar de becket
    Profil pro
    Informaticien multitâches
    Inscrit en
    Février 2005
    Messages
    2 854
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informaticien multitâches
    Secteur : Service public

    Informations forums :
    Inscription : Février 2005
    Messages : 2 854
    Par défaut
    1 - Tu dois regarder du coté du type de term et des locales utilisées

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    echo $TERM
    locale
    2 -

    Le nombre de paramètres que tu peux passer dépend de ton shell

  10. #10
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par becket Voir le message
    Le nombre de paramètres que tu peux passer dépend de ton shell
    Pour moi, ça dépend de la commande invoquée et la façon dont elle a été programmée.

    Parce que quand j'ai trouvé ce nombre 174200 que awk acceptait sans problème, j'ai tenté de les envoyer à grep. Et grep m'a répondu que la liste était trop longue...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Invité
    Invité(e)
    Par défaut
    Zut, la partie suivante pose problème:
    En faisant un print, je vois que ça prend apparemment la liste complète et non le fichier en cours de traitement dans la liste ...
    Le résultat est donc faussé ...

  12. #12
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Je n'arrive pas à reproduire ce comportement, à moins de protéger les noms de fichiers avec des guillemets. Tu n'as pas protégé les espaces?

    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
    $ fic="plop toto.txt"
    $ cat $fic
    toto
    titi
    titi
    titit
    tata
    toto
    titi
    titi
    titi
    tata
    blablabla
    blo
    blimot
    $ awk 'END{print FILENAME}' $fic
    toto.txt
    $ cat "$fic"
    cat: plop toto.txt: Aucun fichier ou dossier de ce type
    $ awk 'END{print FILENAME}' "$fic"
    awk: cannot open plop toto.txt (No such file or directory)
    $

  13. #13
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Je n'arrive pas à reproduire ce comportement
    Pareil

    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
    moi@tux:~/tmp$ cat toto
    toto ligne 1
    toto ligne 2
    toto ligne 3
     
    moi@tux:~/tmp$ cat titi
    titi ligne 1
    titi ligne 2
    titi ligne 3
     
    moi@tux:~/tmp$ awk '{printf("[%s] %d [%s]\n", FILENAME, NR, $0)}' toto titi
    [toto] 1 [toto ligne 1]
    [toto] 2 [toto ligne 2]
    [toto] 3 [toto ligne 3]
    [titi] 4 [titi ligne 1]
    [titi] 5 [titi ligne 2]
    [titi] 6 [titi ligne 3]
    Vu d'ici, FILENAME contient bien le fichier en cours de traitement et non l'ensemble des fichiers passés en paramètres.

    En revanche, NR (numéro d'enregistrement) continue à s'incrémenter alors que j'aurais plutôt imaginé qu'il repartait à 1 pour chaque nouveau fichier...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  14. #14
    Invité
    Invité(e)
    Par défaut
    C'est pas bien de faire des tests quand on est fatigué, il y avait un sort caché plus loin donc forcément ...
    Désolé

    Citation Envoyé par ecatomb Voir le message
    Par contre awk bug quand la variable paramètre contient un accent. Une idée pour résoudre ce problème?
    Sinon, combien de fichier peuvent être passés en paramètre à awk ?
    J'ai aussi trouvé la solution de ce problème : mettre des doubles quote après le simple quote.
    Mais ce n'était pas l'accent qui posait problème mais un espace

    Avant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    END { for (id in tableau) print "xxxxxxxxxxxxxxxxxxxx;"id";"numero_abonne";"tableau[id]";'$parametre';xxxxxxxx" }' $liste_fichier
    Après:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    END { for (id in tableau) print "xxxxxxxxxxxxxxxxxxxx;"id";"numero_abonne";"tableau[id]";'"$parametre"';xxxxxxxx" }' $liste_fichier
    [EDIT]C'est justement à cause du NR que j'ai voulu vérifier le nom du fichier.
    A sa place, il faut utiliser FNR qui marche très bien

    Sinon je me demandais s'il y a trop de fichier à traiter pour awk. Existe-t-il une astuce pour l'augmenter?
    Car c'est franchement très rapide maintenant. Mais quand il y aura trop de fichier à traiter, ça risque de casser >_<
    Dernière modification par Invité ; 14/03/2014 à 00h29.

  15. #15
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    La seule chose que l'on pourrait reprocher est la chaîne de caractère trop longue contenant des fichiers.
    Il faudrait traiter la liste des fichiers en fichier.
    Mais awk ne charge malheureusement pas les fichiers dynamiquement.

    Franchement, si on résume, y a que deux choses qui sont utiles: le numéro de client et la ligne de 11 caractères.
    Un petit programme C++ de débutant qui prend en entrée un fichier contenant la liste de tes cobayes, et ton programme devient difficile à déborder.
    M'enfin bon. L'optimisation se heurte à la flemme du posteur.


    Cela dit sans méchanceté.

  16. #16
    Invité
    Invité(e)
    Par défaut
    C'est bien ça

    J'aurais pu essayé de le faire en C# (que je trouve plus simple que le C++) mais :
    - le serveur où doit tourner le programme ne le gère pas
    - il faut avoir quelque chose facile à comprendre et à modifier

    Le java serait une meilleur piste mais dans ce cas, ce sera une autre personne qui va s'amuser à faire le programme. Ca ne me dérange pas du tout

    En tout cas, merci pour l'aide.

  17. #17
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ecatomb Voir le message
    J'aurais pu essayé de le faire en C# (que je trouve plus simple que le C++) mais :
    - le serveur où doit tourner le programme ne le gère pas
    - il faut avoir quelque chose facile à comprendre et à modifier

    Le java serait une meilleur piste mais dans ce cas, ce sera une autre personne qui va s'amuser à faire le programme. Ca ne me dérange pas du tout
    Ouais, C++, C#, Java. Assembleur aussi ???
    "Attrapper une souris avec un maillet ? Oui en effet l'important ce qui compte c'est le résultat. Alors un maillet, un arc, une catapulte..." (Leodagan, Kaamelott)

    Pour ce genre de tâche, typiquement c'est soit du shell, soit un langage de script facile à implémenter et à maintenir (perl, awk, python, sed)...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  18. #18
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Ouiiii mais tu ne réponds pas à la question de la chaîne de caractères avec des fichiers de noms longs qui la font exploser.
    Plus haut, tu parles de xarg, mais ça ne convient pas car le processus de awk doit être ouvert durant tout le traitement, sinon, il perd le compte.

    Je me suis creusé les nin-ninges et j'arrive à un résultat que je trouve très correct. Pour vous éviter de scruter, quelles sont les idées?
    • D'abord, on mets la liste des fichiers "cibles" dans un fichier. Une liste toute bête. (peu importe qu'elle contienne 1 Million de fichiers)
    • Ensuite, on rentre le nom du fichier dans le fichier. Ceci permet de s'affranchir de la vision simultanément omnisciente et dans le fichier
    • Ensuite, on confie à sed les tâches désespérément systématiques
    • Enfin, on confie à awk le bilan final avec addition, suppression des espaces et zéros inutiles
    • Je présente un script qui fait la liste à la volée des fichiers présents dans le dossier (avec find) mais pour être franc, j'ai utilisé un fichier figé contenant 30 fois le nom du fichier donné en exemple. Le résultat qui suit est donc purement artificiel


    Et, Tata! Voilà! C'est-y pas beau?
    Et aucun shell n'a été maltraité dans cette séquence.

    ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    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
    INFO......................................................
    ABCD 000001
    00........................................................
    01........................................................
    05........................................................
    10........................................................
    20........................................................
    99........................................................
    EFGH 000015
    00........................................................
    01........................................................
    05........................................................
    10........................................................
    20........................................................
    99........................................................
    IJKLM000005
    00........................................................
    01........................................................
    05........................................................
    10........................................................
    20........................................................
    99........................................................
    megafiltre.bash:
    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
    #!/bin/bash
     
    while read fic
    do
        #echo -n $fic
        sed -i '1i \
    '$fic'
    ' $fic
     
        sed '1{
                  s/^...//
                  s/\(.\{18\}\).*/\1/
                  h
                  d
             }
             /^.\{11\}$/!d
             G
             s/\(.....\)\(......\)\n\(.*\)/\3;\1;\2/' $fic
     
        sed -i '1d' $fic
    done < <(find . -type f -name "*") |awk -F';' '{gsub(/ /, "", $2);$1=int($1);tab[$1" "$2] += $3;} END{for (i in tab) print i,tab[i]}'
     
     
    #done <<<"ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    #done <listefic 
    #done < <(find . -type f -name "*")
    Résultat console:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ ./megafiltre.bash
    41 EFGH 450
    41 IJKLM 150
    41 ABCD 30
    Allez, dodo.

  19. #19
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 360
    Par défaut
    Bonjour,

    on peut avoir une idée des limites de passage d'argument avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ xargs --show-limits
    Vos variables d'environnement occupent 1988 octets
    Limite supérieure POSIX de longueur d'argument (sur ce système) : 27964
    Plus petite limite haute POSIX de longueur d'argument (tous systèmes) autorisée : 4096
    Longueur maximale de la commande qui pourrait être utilisée : 25976
    Taille du tampon de commande actuellement utilisé : 27964
    Comme le précise Flodelarab, le passage d'argument avec xargs ne résoudra pas le cas limite, pour le vérifié, il suffit de faire le test en forçant la limite à 1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ echo toto titi | xargs -n 1 awk '{A+=1;printf("Fichier:%s FNR:%d NR:%d A=%d Contenu ==>",FILENAME,FNR,NR,A);print $0}'
    Fichier:toto FNR:1 NR:1 A=1 Contenu ==>toto ligne 1
    Fichier:toto FNR:2 NR:2 A=2 Contenu ==>toto ligne 2
    Fichier:toto FNR:3 NR:3 A=3 Contenu ==>toto ligne 3
    Fichier:titi FNR:1 NR:1 A=1 Contenu ==>titi ligne 1
    Fichier:titi FNR:2 NR:2 A=2 Contenu ==>titi ligne 2
    Fichier:titi FNR:3 NR:3 A=3 Contenu ==>titi ligne 3
    Mais sous gawk, une petite modification du script awk d'origine, permettra de ne fournir qu'un seul fichier en argument (qui contient la liste des fichiers à traiter):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ parametre=toto
    $ cat liste_fichier
    ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ awk '{nom_fichier=$0;while (getline<nom_fichier){if (length == 11) { type_cr=substr($0,1,5);
    nb_cr=substr($0,6,6);
    sub(/.*\//,"",nom_fichier);
    numero_abonne=substr(nom_fichier,4,18)+0
    sub(/ /, "", type_cr);
    tableau[type_cr]+=nb_cr}};close(nom_fichier)}
    END { for (id in tableau) print "xxxxxxxxxxxxxxxxxxxx;"id";"numero_abonne";"tableau[id]";'$parametre';xxxxxxxx" }' liste_fichier
    xxxxxxxxxxxxxxxxxxxx;ABCD;41;3;toto;xxxxxxxx
    xxxxxxxxxxxxxxxxxxxx;EFGH;41;45;toto;xxxxxxxx
    xxxxxxxxxxxxxxxxxxxx;IJKLM;41;15;toto;xxxxxxxx

  20. #20
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    J'aime bien ta méthode disedorgue mais j'ai l'impression d'avoir des problèmes quand le fichier est dans un sous-dossier.
    J'essaye donc de bien comprendre les différentes parties.


    J'ai fait le test suivant qui donne des résultats bizarres ...
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    $ cat liste_fichier
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    output/ABC000000000000000042xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    output/ABC000000000000000043xxxxxxxxxxxxxxxxxxxxxxxxxxxx
     
    $ cat liste_fichier_ko
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
     
    $ gawk '{nom_fichier=$0
    while (getline<nom_fichier)
    {
    if (length == 11) {
     print nom_fichier
     print $0 #ligne
    }
    }
    }' liste_fichier
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ABCD 000001
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    EFGH 000015
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    IJKLM000005
    output/ABC000000000000000042xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ABCD 000001
    output/ABC000000000000000042xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    EFGH 000015
    output/ABC000000000000000042xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    IJKLM000005
    output/ABC000000000000000043xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ABCD 000001
    output/ABC000000000000000043xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    EFGH 000015
    output/ABC000000000000000043xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    IJKLM000005
     
    $ gawk '{nom_fichier=$0
    while (getline<nom_fichier)
    {
    if (length == 11) {
     print nom_fichier
     print $0 #ligne
    }
    }
    }' liste_fichier_ko
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ABCD 000001
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    EFGH 000015
    output/ABC000000000000000041xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    IJKLM000005
    Une idée du problème?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Amélioration de la vitesse de 1er chargement
    Par Sankasssss dans le forum Général Dotnet
    Réponses: 3
    Dernier message: 22/09/2009, 17h46
  2. Réponses: 6
    Dernier message: 30/06/2008, 10h14
  3. Améliorer la vitesse de parcours d'un gros recordset
    Par Vld44 dans le forum Vos contributions VB6
    Réponses: 8
    Dernier message: 28/01/2008, 01h15
  4. Evaluer la vitesse d'un script ?
    Par reski dans le forum Langage
    Réponses: 3
    Dernier message: 19/06/2007, 00h31

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