Forum Programmation.shell Utiliser awk pour calculer la somme d'une ligne jusqu'à une autre.

Posté par  .
Étiquettes : aucune
1
15
août
2012

Slt,

J'ai un fichier dont le contenu est le suivant :

02.086
02.095
02.087
02.080
02.080
02.093
02.090
02.085
04.176
03.083
05.252
03.094
03.095
04.095

j'aimerais pouvoir faire la somme d'une ligne donnée comme point de départ et une ligne comme point d'arrivée (pas forcément la dernière ), genre somme de la ligne 7 à 15 . Quelqu'un saurais comment le faire via awk ?

merci

  • # Dur

    Posté par  (site web personnel) . Évalué à 5.

    Il n'y a que 14 lignes donc pas de ligne 15 :)

    $ awk '{if(NR>=7 && NR<=15){S+=$1}} END{print S}' < d
    26.97
    
    
    • [^] # Re: Dur

      Posté par  (site web personnel) . Évalué à 6.

      En fait juste:

      awk 'NR>=7 && NR<=15 {S+=$1} END{print S}' < d
      
      
      • [^] # Re: Dur

        Posté par  (site web personnel) . Évalué à 3.

        Voilà, et si tu veux glisser ça dans un script shell pour pouvoir t'en resservir tu peux partir de cela:

        #!/bin/sh
        awk -v first_row="$1" -v last_row="$2" 'NR>=first_row && NR<=last_row {S+=$1} END{print S}' < d
        
        
        • [^] # Re: Dur

          Posté par  . Évalué à 2. Dernière modification le 16 août 2012 à 07:46.

          merci juste ce dont j'avais besoin, une chose que je ne comprends néanmoins pas c'est le comportement suivant :

          j'ai dans un script bash utilisé awk de cette manière

          awk    'NR>=$fin,NR==$debut{x+=$0;}END{print x}' /tmp/test.time.txt
          
          

          Il me retourne néanmoins la somme total des lignes au lieu de se contenter de me retourner la somme entre la variable début et fin

          Une explication ?

          • [^] # Re: Dur

            Posté par  . Évalué à 1.

            C'est parce que ta première expression sera vraie jusqu'à la fin de ton fichier (le NR>=$deb), donc le NR==$fin ne la stoppera pas.

            Si tu veux utiliser cette forme, c'est: awk 'NR==$deb,NR==$fin{...

          • [^] # Re: Dur

            Posté par  (site web personnel) . Évalué à 4.

            Bon déjà il faut comprendre la syntaxe :

            pat1 , pat2 {code} : http://www.gnu.org/software/gawk/manual/gawk.html#Ranges

            pour chaque ligne il test si pat1 est vrai, si il est vrai alors il exécute le code à chaque ligne jusqu'à que pat2 soit vrai.

            Donc il faut que NR>=$fin pour qu'il commence à incrémenter la variable x, et il finira lorsque que NR==$debut. Ce qui veut dire si $début=2 et que $fin=4 alors la condition NR>=$fin sera vrai à partir de la ligne 4 mais par contre tu n'auras jamais NR==$debut (puisque NR sera toujours suppérieur à 4 et donc à 2). Et même si tu t'amuse à avoir un début plus grand que la fin, comme NR>=$fin sera vrai à la ligne suivante il va nécessairement traiter toutes les lignes jusqu'à la fin
            Donc ton code additionne tous ce qui est plus grand que $fin sans jamais s'arrêter.

            Maintenant lorsque tu mets $fin dans un awk il ne va pas chercher par magie la variable bash correspondante (c'est expliqué dans tous les tutos, même les plus petits) il va faire :
            - interprétation de la variable fin, je ne le trouve pas donc je le remplace par 0 ce qui donne $0
            - interprétation de $0 c'est à dire toute la ligne

            Donc ton code correspond à :
            awk 'NR>=$0,NR==$0{x+=$0;}END{print x}'

            ce qui fonctionne encore moins et ne correspond pas du tout à ce que tu voulais faire.

            Si tu veux garder ta méthode tu dois plutôt faire :
            awk -v fin=$fin -v debut=$debut 'NR==debut,NR==fin {x+=$0} END {print x}'

            • [^] # Re: Dur

              Posté par  . Évalué à 2.

              merci pour l'explication, faut dire que je commence à peine awk :)

              • [^] # Re: Dur

                Posté par  (site web personnel) . Évalué à 3.

                Je te conseille vivement de t'abonner à comp.unix.shell tu apprendras très vite.

                • [^] # Re: Dur

                  Posté par  . Évalué à 2. Dernière modification le 17 août 2012 à 21:21.

                  ok vais faire un tour .

                  Je me demandais si à part awk et sed, il y avait d'autres utilitaires necéssaire qui sont satellites à bash (dans le meme ordre d'idées que le coreutils)

                  (par exemple je ne compte pas apprendre perl, car je souhaite simplement me focaliser sur le shell bash et ses outils satellites comme awk et sed). Au fait, est ce que le binutils est nécessaire pour le script bash alors qu'on ne fait pas de dev ?

                  • [^] # Re: Dur

                    Posté par  (site web personnel) . Évalué à 3. Dernière modification le 17 août 2012 à 22:11.

                    Apparemment tu partages ma tendance à utiliser l'outil le plus simple qui te permet de faire le travail (car tu préfères apprendre AWK que PERL). Comme bash est un gros shell bien gras, tu peux réfléchir à apprendre sh plutôt que bash. L'avantage est que tu programmeras de façon un peu plus portable — ce qui peut toujours s'avérer utile. Pour la programmation, le gros plus de bash, c'est les tableaux… quelque part j'ai envie de dire que le shell ne sert pas à programmer, mais à décrire un workflow, et que le besoin de tableau témoigne d'un problème qui ne doit pas être résolu dans le shell.

                    En gros l'idée est que si tu utilises beaucoup ton tableau, il vaut peut-être mieux écrire un petit outle pour résoudre ton problème. Sinon, tu peux très bien le coller dans un fichier, voire dans un dossier.

                    Ce livre est souvent controversé, mais je te le recommande tout de même: Unix shell programming de Lowell Jay Arthur (2nd édition, c'est important car souvent dans ce genre de livre, les éditions varient substantiellement). Ce livre est très imprégné de la philosophie Unix et si tu le comprends bien tu sais bien à quoi sert le shell. Le point clef est que le shell sert à décrire un workflow et que le programme que tu coordonnes (avec des pipes) doivent travailler sur une représentation commune des données, la plus simple possible. (XML et JSON sont beaucoup trop complexes!)

                    Exemples:
                    — onsgmls (James Clark) permet de passer d'un SGML à une version validée et facile à traiter en shell (chaque élément, attribut, etc. apparaît sur sa propre ligne).
                    — noweb (Norman Ramsey) utilise un format trivial pour pouvoir piper ses données vers un filtre unix donné par l'utilisateur. (Ce qui au passage te fait une source d'exemples de scripts awk.)

                    Le point clef de la programmation shell est donc la création de programmes élémentaires qui travaillent sur une représentation commune des données, si possible assez simple pour éventuellement être travaillée avec sed, awk, … (cela évite d'avoir à coder des analogue de awk et sed pour la représentation en question).

                    Les défauts de la plupart des gens:
                    — sous-utilisation du système de fichiers (le plus simple pour implémenter une table associative est d'utiliser le système de fichiers, Lowell Jay Arthur explique ça très bien).
                    — sous-utilisation des pipes nommés pour les IPC.
                    — utilisation de echo lorqu'il faut utiliser printf (echo sert à afficher un message pour l'utilisateur, tout le reste doitr être géré par printf).

                    Quelques conseils pour se simplifier la vie:
                    — pour toutes tes interpolations de type backquote un tant soit peu compliquée, écris une fonction auxiliaire: tu éviteras toutes sortes de migraines liées aux échappements et aux quotes!
                    — cale toutes tes boucles while read dans une fonction à part, cela te simplifiera aussi la vie!

                    Je me demandais si à part awk et sed, il y avait d'autres utilitaires necéssaire qui sont satellites à bash (dans le meme ordre d'idées que le coreutils)

                    En gros les thématiques de bases sont:

                    • fichiers: date (pour les noms horodatés), mv, cp, rm, tar, find, xargs, mktemp ou sa variante qui marche.

                    • base de données: join, paste, etc. (pour préparer ton input à awk! et trop souvent méconnus)

                    • filtres: sort, sed, awk, cut, head, tail, grep.

                    • portabilité: command.

                    • make

                    Ensuite viennent les outils correspondant au domaine de ton problème:

                    • unix: stat, ps, id, /etc/passwd, etc.

                    Bon courage et amuse-toi bien!

                    (PS la seconde édition du livre de Lowell Jay Arthur est complètement obsolète — je crois qu'elle parle de System V si bien qu'aucun des exemples du livre ne marche directement, cela fait travailler!)

                  • [^] # Re: Dur

                    Posté par  (site web personnel) . Évalué à 2.

                    Je me demandais si à part awk et sed, il y avait d'autres utilitaires necéssaire qui sont satellites à bash (dans le meme ordre d'idées que le coreutils)

                    oui en bash pour le traitement des fichiers c'est surtout awk et sed (qui sont des langages de programmation à eux tout seul).

                    Pour les autres commandes il faut juste savoir ce qu'elles font et avoir un peu d'astuce pour les combiner de la meilleur façon possible. La page wikipedia http://fr.wikipedia.org/wiki/Commandes_Unix présente déjà une bonne base.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.