Forum Linux.général Que prendre entre sed et awk ?

Posté par  .
Étiquettes :
2
30
août
2011

Bonjour tout le monde,

je me demande lequel de ces outils, entre sed et awk, est le plus adapté à ce que je veux faire.
Je voudrais prendre sur l'entrée standard (fichier ou par tube) un texte, vérifier chaque mot par des expressions régulières et, selon l'expression trouvée pour le mot, l'entourer par des balises (disons des balises HTML).
La sortie est un fichier texte ou alors la sortie standard.

J'ai lu les articles sed et awk sur Wikipédia et je pense que ces deux outils me permettrait de faire ce que je veux.

Mais j'hésite entre l'un ou l'autre, car je n'ai jamais pratiqué aucun des deux, donc je voudrais bien que vous me donniez vos conseils pour le choix :)

Cordialement.

  • # perl

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

    forcément, mieux vaut prendre perl :-)

    sinon, à défaut, awk ('fin gawk), surtout s'il faut garder le contexte d'une ligne à l'autre.

    • [^] # Re: perl

      Posté par  . Évalué à 0.

      awk ('fin gawk), surtout s'il faut garder le contexte d'une ligne à l'autre.

      Je peux traiter chaque ligne indépendamment. ça ne posera aucun problème (au contraire, ça m'arrange).

  • # celui que tu maitrises

    Posté par  . Évalué à 1.

    ca parait con, mais entre un outil que tu matrises et un qui fait bien ce que tu voudrais mais que tu ne connais pas, parfois vaut mieux prendre celui que tu maitrises.

    bon sinon, en fait ca va dependre, du nombre de traitement, de la recurrence de ce que tu recherches...

    et comme dit plus haut, tu as aussi l'alternative Perl qui de faire un vrai programme avec des boucles, recherche/remplace, des ouvertures/fermetures de fichiers...

    • [^] # Re: celui que tu maitrises

      Posté par  . Évalué à 1.

      Merci pour vos réponses.

      Je ne maîtrise justement ni l'un ni l'autre. En fait vais m'orienter vers la lecture de la doc de l'un ou de l'autre selon vos conseils.

      bon sinon, en fait ca va dependre, du nombre de traitement, de la recurrence de ce que tu recherches...

      le nombre de traitement peut être assez élevé, mais si le programme sed ou awk bufferise ligne par ligne il n'y aura aucun problème.

      Pour Perl, je trouve que c'est un peu overkill (puis je ne le maîtrise pas non plus).

  • # exemple awk

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

    Salut,

    voici un exemple court (one-liner) en awk de parsing d'un fichier avec foo bar base qux, un élément par ligne dans /tmp/l :

     awk 'BEGIN{print "<html>\n<head>\n<title></title>\n</head>\n<body>"}
    /(^foo|^bar|^qux)/{printf "<div class=\x27%s\x27>%s</div>\n", $0, $0}
    END{print "</body>\n</html>"}' /tmp/stdin
    
    

    Ce qui donne : Titre de l'image

    (le html passe pas ici)

    On ne peut pas mettre d'array dans le string...

    • [^] # Re: exemple awk

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

      comment ça le html ne passe pas ?

      <html>
      <head>
      <title></title>
      </head>
      <body>
      <div class='foo'>foo</div>
      <div class='bar'>bar</div>
      <div class='qux'>qux</div>
      </body>
      </html>
      
      

      je te laisse regarder l'aide-mémoire lorsque tu postes un commentaire ou sinon l'Aide-Edition du wiki pour trouver comment faire :-)

      • [^] # Re: exemple awk

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

        En preview mode, si on indente le code avec le bouton prévu à cet effet et qu'on a un mot juste au dessus çà donne ça http://ompldr.org/vYTRlMg baud123

        Pour en revenir à notre intéressé, oui tu peut jouer avec les mots présents sur chaque ligne.

        le premier mot = $1 le deuxième $2...

        le %s de printf représente l'argument donné après la fin de chaîne entre "quotes".

        Exemple :

        awk 'BEGIN{print "<html>\n<head>\n<title></title>\n</head>\n<body>"}
        /(^foo|^bar|^qux)/{printf "<div class=\x27%s\x27>%s</div>\n", $2, $1}
        END{print "</body>\n</html>"}' /tmp/stdin
        
        
        $ cat /tmp/stdin 
        foo fc
        bar bc
        base pouet
        qux fq
        
        

        On ne peut pas mettre d'array dans le string...

        • [^] # Re: exemple awk

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

          WTF o_O un bouton ? ah, ça code
          la "fameuse barre de mise en forme" que je ne vois pas : je n'utilise jamais ces trucs defectives by design (visiblement t'es tombé sur un bug ou le bouton n'est pas prévu pour cela, à remonter dans le suivi au besoin), un wiki c'est une syntaxe simplifiée, pas du pousse-bouton pour moi. C'est ce qui fait que plein de monde ne réussit pas encore à faire des listes correctes (c'est ballot d'oublier de passer une ligne avant :/)

          en l'occurence,

          ```html
          <html>code html toussa</html>
          ``` 
          
          

          fonctionne très bien (et pour citer la syntaxe wiki Markdown, la balise ```text fonctionne très bien aussi)
    • [^] # Re: exemple awk

      Posté par  . Évalué à 0.

      En effet, ça à l'air de coller à mes attentes. Donc on peut faire correspondre mot par mot avec awk (si je comprends bien le code) ?

  • # sed !

    Posté par  . Évalué à 4.

    Je voudrais prendre sur l'entrée standard (fichier ou par tube) un texte, vérifier chaque mot par des expressions régulières et, selon l'expression trouvée pour le mot, l'entourer par des balises (disons des balises HTML).

    Si tu cherches juste à rechercher+remplacer, alors sed est l'outil idéal. Par exemple :

    $ sed -r -e 's/\<(foo[^[:space:]]*bar)\>/<div class=\x27foobar\x27>\1<\/div>/;'
    
    

    Cette expression va rechercher tous les mots débutant (\<) par foo et se finissant (\>) par bar, et les encadrer par un div de la classe foobar. [^[:space:]]* signifie zéro ou plus caractères qui ne sont pas de la classe [:space:], c'est à dire tout sauf espace et tab. L'utilisation de parenthèses () sur le pattern permet de le rappeler avec la back-reference \1.

    je n'ai jamais pratiqué aucun des deux

    Alors bon courage ! Les expressions régulières forment un monde vraiment abscons la première fois que tu t'y colles. Par contre, quand tu maîtrises ( ce qui n'est pas encore mon cas ! ), ça devient d'une puissance !...

    Voici un petit tutorial avec pleins d'astuces sed.

    Bon courage !

    Hop,
    Moi.

  • # Sed

    Posté par  . Évalué à 3.

    C'est marrant parce que pour moi, ça :

    Je voudrais prendre sur l'entrée standard (fichier ou par tube) un texte, vérifier chaque mot par des expressions régulières et, selon l'expression trouvée pour le mot, l'entourer par des balises (disons des balises HTML).

    Ça correspond plus à sed qu'à awk. Il ne veux pas faire d'entête ou de pied de page et il veut traiter n'importe quel mot de chaque ligne donc un truc comme ça me semble mieux convenir (pas tester la rêgle) :

    sed 's/\(salut\|hello\)/<a>\\1<\/a>/g'
    
    

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # entre les deux....

    Posté par  . Évalué à 3.

    entre les deux les habitudes sont très différentes
    awk est plus ressemblant à du codage algorithmique, alors que sed a un aspect de codage plus logique.

    pour faire simple si tu as souvent besoin de conditionnements imbriqués mieux faut que tu maitrises awk bien et un peu sed, et si tu fais plus du traitement assez simple, mais sur des gros volumes de données ou tres souvent et à la volée, mieux vaut concentrer ton apprentissage sur sed et connaitre moins bien awk...

    l'autre avantage de awk sur sed ?
    c'est plus lisible donc si tu reprend le script awk de quelqu'un d'autre tu le comprends de suite ou presque.
    alors que sed sera peut être un poil plus efficace, (et encore quand c'est bien utilisé), mais pour relire un code de plus de 10 lignes si ça n'est pas commenté ou accompagné d'une explication, ça ira plus vite de re-coder une procédure à toi.

    • [^] # Re: entre les deux....

      Posté par  . Évalué à 1.

      J'ai essayé de retrouver un exemple de script qui découpait des fichiers postscript écrit en sed (script de quelques lignes) mais je le ne retrouve pas.

  • # RE

    Posté par  . Évalué à 1.

    Veuillez m'excuser mais j'ai oublié un petit détail : je veux en effet une entête et un pied de page, car j'ai besoin de générer du HTML au final.

    • [^] # Re: RE

      Posté par  . Évalué à 2.

      awk dispose des directives BEGIN et END qui te permettent d'exécuter des traitements avant et après avoir parsé ton fichier.

      Tu peux définir par exemple une fonction entete et pied_de_page qui t'affichent ton entete et pied de page et les appeler dans la clause BEGIN et END respectivement.

      • [^] # Re: RE

        Posté par  . Évalué à 1.

        Donc je vais plutôt me tourner vers awk (car j'ai vraiment besoin de mon header et de mon footer).

        Merci pour vos réponses :)

        • [^] # Re: RE

          Posté par  . Évalué à 1.

          je vais plutôt me tourner vers awk (car j'ai vraiment besoin de mon header et de mon footer).

          Pourquoi ? Avec sed, c'est tout à fait possible aussi. Et même sans faire intervenir la syntaxe sed, en plus :

          $ cat hdr_sed_foot.sh
          #!/bin/sh
          
          print_header() {
              printf "<html>blabla...\n"
          }
          print_footer() {
              printf "...blabla</html>\n"
          }
          
          print_header
          sed -r -e 'SED_EXPERESSION'
          print_footer
          
          

          Et voilà !

          Hop,
          Moi.

          • [^] # Re: RE

            Posté par  . Évalué à 2.

            Je ne veux pas troler, mais vu comment il présente les choses, il aura moins de mal avec Awk qu'avec Sed.

            • [^] # Re: RE

              Posté par  . Évalué à 2.

              On peut insérer un header et un footer avec sed et ce n'est pas compliqué:

               echo 'axe' | sed -e '1iDEBUT' -e '$aFIN' -e 's/x/y/g'
              
              

              donne:

              DEBUT
              aye
              FIN
              
              
              • [^] # Re: RE

                Posté par  . Évalué à 2.

                Je trouve que ce genre de truc en SED devient vite illisible. SED est très efficace pour des actions sur recherche de motifs, mais pour le reste, pour tout ce qui ressemble un peu à de la programmation, awk est bien plus efficace.

                • [^] # Re: RE

                  Posté par  . Évalué à 1.

                  Il est vrai que je dois rester dans une optique de programmation qui, je pense, sera plus adaptée au problème, puis la notion de "champ" de awk me permettrait facilement de travailler mot par mot, je me trompe ?

                  • [^] # Re: RE

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

                    oui, les $1, $2, $3 (si c'est un tableau avec des données par colonne par exemple ou un fichier csv) peuvent être bien pratiques en awk.

                    • [^] # Re: RE

                      Posté par  . Évalué à 0.

                      C'est un nombre imprévisible de lignes par mot que je dois traiter. Il pourrait même ne pas y en avoir.

                      • [^] # Re: RE

                        Posté par  . Évalué à 3.

                        Un nombre imprévisible de lignes par mots ou de mots par ligne ?

                        si c'est bien un nombre indeterminé de mots par ligne tu as la possibilité au choix d'utiliser la variable NR (nombre de records par ligne), ou alors tu peux utiliser la fonction split sur $0 qui remrésente la ligne entière.

                        • [^] # Re: RE

                          Posté par  . Évalué à 1.

                          Oups, je voulais bien-sûr dire un nombre imprévisible de mots par ligne ;)

                          Merci, je vais me renseigner sur NR et le split sur $0 pour voir comment je peux matcher mot par mot.

Suivre le flux des commentaires

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