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 :

Passer une variable externe à awk


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 64
    Par défaut Passer une variable externe à awk
    Hello,

    Je ne sais pas si c'est possible, je pense que oui, mais tous mes tests se sont révélés infructueux.

    J'ai un résultat du type :

    toto1 xxx yyy
    toto2 zzz aaa
    toto3 bbb ccc

    Sachant que pour avoir ce résultat, je le passe à une moulinette qui me fait un grep sur les éléments de la colonne du milieu (un grep $i).
    Moi ce qui m'intéresse, c'est uniquement la première colonne.

    Je pourrais faire un truc du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep $i | awk '{print $1}'
    Mais c'est crade, je ne veux qu'un seul process.

    Aussi, je voudrais tout imbriquer dans awk, mais comment faire pour faire passer mon $i dans mon awk ?

    un truc du style : mais ça ne marche pas !

    Auriez-vous une idée ?

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 635
    Par défaut
    Bonjour,

    Citation Envoyé par man awk
    -v var=val
    --assign var=val
    Assign the value val to the variable var, before execution of the program begins.
    Such variable values are available to the BEGIN block of an AWK program.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 64
    Par défaut
    En fait, j'ai précisément commencé par le man et par ce test :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -v var=$i "/var/ {print $1}"
    J'ai essayé de plusieurs façons différentes, mais rien à faire..

    exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {bb}@serv# cat test2
    zrezrezr sfdsfdf
    ezrezrezrz dsfds
    {bb}@serv# toto=sfdsfdf
    {bb}@serv# echo $toto
    sfdsfdf
    {bb}@serv# awk -v var=$toto '/var/ {print $1}' test2
    {bb}@serv#
    {bb}@serv# awk '/sfdsfdf/ {print $1}' test2
    zrezrezr
    J'utilise mal awk ?

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 635
    Par défaut
    on ne peut mettre que des strings entre /
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    awk -v v="sfdsfdf" '($0 ~ v){print $1}' test2
    zrezrezr
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 946
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 946
    Par défaut
    Salut,

    Une autre solution consiste à sortir de la syntaxe de awk et d'utiliser la variable initiale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ cat f1
    zrezrezr sfdsfdf
    ezrezrezrz dsfds
     
    $ toto=sfdsfdf
     
    $ echo ${toto}
    sfdsfdf
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk '/'${toto}'/ { print $1 }' f1
    zrezrezr

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 799
    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 799
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par jhfra Voir le message
    Je pourrais faire un truc du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep $i | awk '{print $1}'
    Mais c'est crade je ne veux qu'un seul process.
    Ah bon ??? Et depuis quand l'utilisation des pipes (qui est une des bases du scripting shell dans laquelle chaque commande ne fait qu'une chose mais la fait bien et c'est en les chainant qu'on peut produire des trucs complexes) est-elle qualifiée de "crade" ???
    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]

  7. #7
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par jhfra Voir le message
    Aussi, je voudrais tout imbriquer dans awk, mais comment faire pour faire passer mon $i dans mon awk ?

    un truc du style : mais ça ne marche pas !

    Auriez-vous une idée ?
    On peut aussi faire comme ça mais en faisant attention au contenu de la variable i:
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk "/$i/"' {print $1}'

  8. #8
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 335
    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 335
    Par défaut
    Bonjour,

    Comme on est sous gnu, on peut aussi se passer de awk et le faire avec grep :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ cat plop
    toto1 xxx yyy
    toto2 zzz aaa
    toto3 bbb ccc
    $ toto=xxx
    $ grep -Po '.*(?='$toto'.*)' plop
    toto1

  9. #9
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 64
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour


    Ah bon ??? Et depuis quand l'utilisation des pipes (qui est une des bases du scripting shell dans laquelle chaque commande ne fait qu'une chose mais la fait bien et c'est en les chainant qu'on peut produire des trucs complexes) est-elle qualifiée de "crade" ???
    Oui, j'estime que d'appeler 2 binaires (donc minimum 2 process) pour faire ce que l'on peut très bien faire avec un seul binaire (et donc un process), c'est un peu crade. Si il n'y a pas d'autre solution, je ne dis pas.. Mais sachant tout ce qu'on peut faire avec awk ou sed, c'est dommage de ne pas chercher à utiliser pleinement ces outils.

    Je suis très loin de coder proprement, mais je m'efforce d'utiliser de la manière la plus optimale possible les outils qui me sont fournis, ce qui me permet également de mieux les comprendre

    Par ailleurs, sur un traitement de quelques lignes et assez court, le temps cpu pris par un bête pipe ne se ressentira pas, mais des traitements plus lourds et complexes, on perd potentiellement en temps CPU.

    Bref, je suis doublement gagnant si j'essaye d'optimiser mon code autant que possible dès le départ

    Par contre, l'idée de ne vouloir utiliser systématiquement qu'un process pour ce genre de traitement atteind vite ses limites.. inutile d'émuler sur 3 ou 4 lignes de codes illisible avec awk (ou sed) ce qu'un bête binaire est à côté capable de faire très simplement.. de une, en temps cpu l'émulation de la fonction que l'on cherche à faire n'est peut être pas optimale en temps cpu (appels systems etc..) et de deux, ça alourdit visuellement le code, le rendant vraiment très chiant pour le debug.

    Bref, il faut trouver le juste milieu. Mais dans le cas présent, je pense que je peux faire l'effort (avec votre aide !) de trouver une solution quand même plus propre qu'un awk |grep

    Merci à tous pour vos idées, je teste ça ce matin.

  10. #10
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 64
    Par défaut
    En fait, vos 3 solutions fonctionnent

    Merci à tous !

  11. #11
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 335
    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 335
    Par défaut
    Ton argument sur l'optimisation n'est pas clair, je m'explique:

    Ici, d'après ce que l'on comprend de ton problème:
    Pour une ligne donnée, tu veux extraire une partie de celle-ci qui est différente du motif de recherche (qui de plus est assez bien borné concernant leur position).
    L'autre point important de ton problème, c'est que le motif est variable, et j'en viens à l'aspect que tu ne nous à pas fourni de ton problème:

    Quel est le but de cette variabilité du motif dans le contexte du problème final ?
    Tu auras une liste de motif et tu bouclera dessus pour faire les extractions ou c'est juste pour un seul motif sur demande ?

    Si c'est le cas de la boucle, ton approche n'est pas vraiment la meilleure sur un point de vu optimisation cpu surtout si tu as des centaines de fichiers de milliers voir de millions de lignes à traiter.
    Un petit dev en awk voir en perl d'une dizaine de ligne (donc plus complexe que la simple solution grep ou awk donnée) basé sur des tableaux de hash peut permettre un gain de temps plus que conséquent (de plusieurs minutes pour le traitement d'un fichier, on peut passer à quelques dizaines de secondes).

  12. #12
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 64
    Par défaut
    @disedorgue :

    J'ai bien une liste de motif, et je dois boucler dessus (d'où la variabilité du motif) pour extraire mes chaines.

  13. #13
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 335
    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 335
    Par défaut
    Voici un petit exemple en awk qui donne l'approche de mon post précédent, mais celui-ci ne fonctionnera que si les motif sont des chaines et non pas des expressions regulières:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ cat fich.motif 
    valx2
    valz2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ cat fich.csv
    name1;name2;name3;name4;name5;name6;name7;name8;name9;name10;
    val1;val2;val3;val4;val5;val6;val7;val8;val9;val10;
    valx1;valx2;valx3;valx4;valx5;valx6;valx7;valx8;valx9;valx10;
    valy1;valy2;valy3;valy4;valy5;valy6;valy7;valy8;valy9;valy10;
    valz1;valz2;valz3;valz4;valz5;valz6;valz7;valz8;valz9;valz10;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ awk -F\; 'FNR == NR {X[$0]=1 ; next} ; X[$2] { print $1 }' fich.motif fich.csv 
    valx1
    valz1

  14. #14
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 799
    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 799
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jhfra Voir le message
    Oui, j'estime que d'appeler 2 binaires (donc minimum 2 process) pour faire ce que l'on peut très bien faire avec un seul binaire (et donc un process), c'est un peu crade
    Exact, bien défendu ta position. Effectivement moi aussi je préfère utiliser grep fichier plutôt que cat fichier |grep.
    Mais ce n'était pas vraiment explicite dans ta première formulation. J'ai cru que tu disais que c'était l'utilisation des pipes de façon générale qui était "crade"...
    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]

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

Discussions similaires

  1. Passer une variable à printf par un awk
    Par DIE dans le forum Shell et commandes POSIX
    Réponses: 3
    Dernier message: 13/02/2013, 15h42
  2. Réponses: 2
    Dernier message: 10/09/2007, 16h43
  3. [Custom Tags 1.2] Passer une variable comme valeur d'attribut d'un tag jsp
    Par Pi2 dans le forum Taglibs
    Réponses: 7
    Dernier message: 16/09/2005, 14h44
  4. Passer une variable entre deux fenêtres
    Par DeezerD dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 17/08/2005, 09h52
  5. [Struts] Passer une variable dans l'url
    Par pilz dans le forum Struts 1
    Réponses: 2
    Dernier message: 30/03/2005, 15h23

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