Forum Linux.débutant Commande awk

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
5
mai
2015

Bonjour,

Je suis étudiant et je commence juste à utiliser Linux. Je suis dans la création d'un scripts ou je rencontre un problème.
Je voudrais sélectionner, dans un tableau que j'ai créé, une valeur numérique mais je n'y arrive pas, après m'être renseigné voila l'idée que j'ai mais en vain.

Dans mon scripts j'aimerais sélectionner la valeur de la masse molaire de mon tableau, en voici les premières lignes:
SYMBOLE | NOM_ELEMENT | NUMERO_ATOMIQUE | MASSE_ATOMIQUE | FAMILLE | ETAT_PHYSIQUE
H | hydrogene | 1 | 1,0079 | non_metaux | gaz
He | helium | 2 | 4,OO26 | gaz_nobles | gaz

J'aimerai afficher la masse molaire j'ai donc pour le moment ceci:

#!/bin/csh

echo "Atome dont vous voulez la masse molaire"
read atome
grep $atome Tableau_Periodique.txt | awk 4

Voila donc mes questions:
- Pourquoi ai-je comme réponse, atome: Undefined Variable
- Comment sectionner juste la valeur numérique de la masse molaire de l'atome concerné dans mon fichier Tableau_Periodique.txt ?

Dans l'attente d'une réponse de votre part, je vous remercie d'avance.

Cordialement,
Vivianm

  • # manuel, shell, etc

    Posté par  . Évalué à 4.

    je ne connais pas le comportement du shell csh

    mais ton code est correct en bash.

    ensuite le manuel de awk (que tu obtiens avec man awk ) va t'expliquer que :
    * l'option -F permet de preciser le delimiteur de champs, dans ton ca ca serait le '|' (barre verticale, appeler pipe)
    * qu'il faut ensuite lui donner des instructions pour imprimer le resultat à l'ecran '{action1;action2]'

    la commande deviendrait alors :
    grep $atome fichier.txt | awk -F'|' '{print $4}‘

  • # Sans le grep ?

    Posté par  . Évalué à 1.

    Du coup je me suis dis que le grep était de trop et qu'on devait pouvoir se limiter à awk:

    awk -F'|' -v choice="$atome" 'NR > 1 && $1 == choice { print $4; }'
    

    Mais le test d'égalité ne semble pas fonctionner à cause des espaces, la commande suivante fonctionnant:

    sed 's/ //g' ./fichier | awk -F'|' -v choice="$atome" 'NR > 1 && $1 == choice { print $4; }'
    

    Mais dans ce cas j'introduis sed, et ajouter des outils n'était pas le but.

    • [^] # Re: Sans le grep ?

      Posté par  . Évalué à 2. Dernière modification le 06 mai 2015 à 01:26.

      awk -F'|' '/'$atome'/ {print $4}' fichier
      ```Si tu veux rien retourner lorsque la valeur passée en variable correspond à la première ligne du tableau :
      

      awk -F'|' '/'$atome'/ && NR > 1 {print $4}' fichier
      ```

      • [^] # Re: Sans le grep ?

        Posté par  . Évalué à 5. Dernière modification le 06 mai 2015 à 01:33.

        Saleté de syntaxe wiki …

        Sans sed :

        awk -F'|' '/'$atome'/ {print $4}' fichier

        Si tu veux rien retourner lorsque la valeur passée en variable correspond à la première ligne du tableau :

        awk -F'|' '/'$atome'/ && NR > 1 {print $4}' fichier

        Enfin si tu veux restreindre le test sur le 1er champ :

        awk -F'|' '$1 ~ /'$atome'/ && NR > 1 {print $4}' fichier
  • # Pas besoin de awk

    Posté par  . Évalué à 3.

    Awk permet de faire de l’analyse de fichier ligne à ligne en gérant des états…

    Tu peux utiliser cut :

    grep $atome Tableau_Periodique.txt | cut -d'|' -f 4

    Et même un petit coup de sed :

    grep $atome Tableau_Periodique.txt | sed 's%^[^|]*|[^|]*|[^|]*|\([^|]*\).*$%\1%'
    • [^] # Re: Pas besoin de awk

      Posté par  . Évalué à 3.

      c'est vrai que le sed est tout de suite plus lisible :p

      • [^] # Re: Pas besoin de awk

        Posté par  . Évalué à 2. Dernière modification le 06 mai 2015 à 23:55.

        c'est vrai que le sed est tout de suite plus lisible :p

        Tiens, pour que j’apprenne un truc. Peut-on écrire l’expression sans la répéter bêtement ?

        [^|]*| est dire je la veux trois fois. Je suis certain que ça doit être possible, mais je ne sais pas comment l’écrire.

        • [^] # Re: Pas besoin de awk

          Posté par  . Évalué à 2.

          oui avec le modificateur numéraire {nmin,nmax}, qui peut aussi s'écrire {n}, dans le cas où nmin et nmax sont égaux.

          ce qui donne en gros un un

          sed -r 's/^([^|][|]){3}([^|]*?)[|].*/\2/'

          tu peux aussi utiliser les modificateur de quantité pour avoir les *, + et ? en non gourmand, cela se fait facilement avec perl

          perl -pe 's/^(.*?[|]){3}(.*?)[|].*/\2/'

          et on peut combiner le tout avec grep et les perl regexp:)

          grep -o -P "^$symbole\|(.*?\|){3}\K(.*?)(?=\|)" 
          
          #ou 
          grep -o -P "$atome\|(.*?\|){2}\K(.*?)(?=\|)"

          et hop magie ;)

          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

          • [^] # Re: Pas besoin de awk

            Posté par  . Évalué à 2.

            oui avec le modificateur numéraire {nmin,nmax}, qui peut aussi s'écrire {n}, dans le cas où nmin et nmax sont égaux.

            Pour moi, ça ne s’applique que au caractère précédent (1 seul).

            Sinon, aucun de tes exemples sed ou grep ne marche sur ma ubuntu :-( du boulot.

            • [^] # Re: Pas besoin de awk

              Posté par  . Évalué à 2.

              Pour moi, ça ne s’applique que au caractère précédent (1 seul).

              C'est pour ça qu'on met des ()

              c'est a cause des ' ' avant les | que je n'avais pas reproduit ;) d'ailleurs je n'avait pas le même tableau

              voici ce qui marche pour la masse atomique

              \grep -o -P "helium\s*\|(.*?\|){1}\K(.*?)(?=\|)" /tmp/perd.txt

              à noter que le 1 peut être remplacé par 0 si tu veux le n° atomique ;)

              Il ne faut pas décorner les boeufs avant d'avoir semé le vent

    • [^] # Re: Pas besoin de awk

      Posté par  . Évalué à 2.

      +1 pour la commande cut. J'y ai pensé immédiatement aussi.

      De manière générale je pense que certaines commandes Unix, qui répondent pourtant chacune à un besoin précis et très fréquent : cut, join, column, etc… restent méconnues et que beaucoup de gens pensent être obligés d'utiliser des couteaux suisses tels que awk ou sed (voir un script PHP/Zend…) pour des besoins basiques, au final utiliser ces usines à gaz de manière relativement triviale.

      Après je suis conscient que lorsque l'on maîtrise totalement un outil comme sed on a pas trop de raison de chercher à utiliser autre chose pour faire quoi que ce soit à base d'édition automatisée de fichiers texte… Ne serait-ce que pour ne pas perdre la maîtrise de cette syntaxe si particulière :)

    • [^] # Re: Pas besoin de awk

      Posté par  . Évalué à 2.

      Meme pas besoin de cut.

      un while read read bien senti en modifiant la variable d'environnement FS devrait faire l'affaire.

      Par contre en pratique, j'ai remarqué que awk mettait moins de temps que le while read sur des flux important. Ca doit s'expliquer par le fait que awk évalue les expressions qui lui sont passées une fois tandis qu'une boucle while évalue les expressions à chaque passage dans celle-ci.

      Autre inconvénient de awk : pas uniforme sur tous les systèmes : hp, solaris et aix ont pas mal de différences, et il y a les extensions GNU que l'on ne touve pas par exemple sur un awk BSD.

Suivre le flux des commentaires

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