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 :

AWK et gsub problème de crochet


Sujet :

Shell et commandes GNU

  1. #1
    DIE
    DIE est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 101
    Par défaut AWK et gsub problème de crochet
    Bonjour,

    Je souhaiterai substituer un mot de la forme [VAR] par ${VAR} sachant
    que VAR est une variable, le problème vient des crochets qui ne peuvent
    être banalisé que par les barres obliques / /
    j'ai beau cherché depuis des heures rien n'y fait
    merci de votre aide

    VAR=TETO

    awk 'gsub(/\[VAR\]/,"${"VAR"}")

  2. #2
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bonsoir,

    Je crois que la commande awk n'est pas la plus appropriée pour faire ce genre de travail, bien que ce soit possible. D'autant que la syntaxe utilisée est assez approximative. La commande sed ira certainement mieux, la preuve:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed -i -e 's/\[VAR\]/${VAR}/g' fichier.txt

  3. #3
    DIE
    DIE est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 101
    Par défaut
    oui merci j'ai réussi en SED
    mais en fait j'utilise un script en pur AWK donc pas question d'y
    introduire du SED.
    Quelqu'un a une autre solution ?
    est-ce vraiment impossible ?

  4. #4
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bon, ben avec awk ça donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '{gsub(/\[VAR\]/, "${VAR}"); print}' fichier_entree > fichier_sortie

  5. #5
    DIE
    DIE est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 101
    Par défaut
    non ça ne fonctionne pas, VAR étant une variable, elle n'est pas substituée à cause des / / ces derniers étant indispensable pour échapper les [ ]

    une autre idée ?

  6. #6
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    J'aimerais voir un extrait du fichier avant et du fichier après. Je ne connais pas ton problème alors il est important que tu fasses l'effort de l'exposer le plus clairement possible.

  7. #7
    DIE
    DIE est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 101
    Par défaut
    ok je vais essayer d'être le plus précis possible.
    je dois écrire un script 100% en AWK, ce script va lire un fichier en entrée et remplacer toutes les valeurs entre crochet [variable] par ${variable}
    sachant que la substitution se fait QUE si la variable est présente dans les variables d'environnement (d'où l'utilisation de la commande ENVIRON[])

    - par exemple si le fichier traitée contient une ligne :
    salut ça va [LOGIN] ? tu es où [PWD] et ta soeur [COUCOU]

    - la sortie doit être
    salut ça va ${LOGIN} ? tu es où ${PWD} et ta soeur [COUCOU]

    - et l'execution eventuelle
    salut ça va xxcol ? tu es où /home/xxcol et ta soeur


    Mon script AWK complet

    la substitution qui me pose problème est gsub(/\[var\]/,"${"var"}",LIGNE)


    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
     
    #!/usr/bin/awk  -f
     
    BEGIN   {
    #system("cat _var")
    print "\nResultat\n"
            }
    #
    ($0 !~ /^#/ && $0 !~ /^$/)      {
     
            LIGNE=$0 ; while(match($0,/\[[A-Z]*\]/))        {
     
            var=substr($0, RSTART+1 , RLENGTH-2)
     
                    if (ENVIRON[var] != "")                         {
     
                                    gsub(/\[var\]/,"${"var"}",LIGNE)
                                                                    }
                    else
                                    {print "Variable d'environnement non résolue : " var}
     
                    $0=substr($0, RSTART + RLENGTH)
                                                            }
                                    print LIGNE
                                    }

  8. #8
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Difficile d'exposer un problème clairement... Voici ce que j'ai compris:

    Il faut écrire un script awk qui prend un paramètre, le nom d'une variable d'environnement (comme HOME, PATH ou HOSTNAME). Si la variable existe et est non vide, alors il faut remplacer, dans le fichier source, la chaîne de caractère "[VAR]" par le contenu de la variable. Sinon on ne change rien au fichier.

    Si c'est bien cela, le code ci-après devrait fonctionner correctement.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    awk -v v=HOME '
    BEGIN {if (ENVIRON[v] != "") {a = 1}}
    {
      if (a == 1) {gsub(/\[VAR\]/, ENVIRON[v])}
      print
    }' fichier_entree > fichier_sortie
    Le paramètre de la commande awk est "-v v=HOME". On peut le remplacer par "-v v=TOTO" (pas de modif puisque TOTO n'existe pas) ou par "-v v=PATH".

  9. #9
    DIE
    DIE est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 101
    Par défaut
    heu non c'est pas ça du tout

    Le fichier TOTO contient :
    salut ça va [LOGIN] ? tu es où [PWD] et ta soeur [COUCOU]

    et j'execute ce fichier TOTO ainsi :
    monscript.awk TOTO

    Si le contenu du fichier TOTO contient une variable d'environnement entre crochet alors il la substitue sinon il la laisse tel quel

  10. #10
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Il est vraiment important d'expliquer correctement (d'ou ma signature). Ton explication devient un peu plus claire, je vais la reformuler comme je l'ai comprise:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    une des lignes du fichier d'entrée:
    salut ça va [LOGNAME] ? tu es où [PWD] et ta soeur [COUCOU]
    
    donnera en fichier de sortie:
    salut ça va jmelyn ? tu es où /local/scratch et ta soeur [COUCOU]
    Si c'est bien cela, voici une commande awk qui marche.
    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
    awk '
    {
      for (champ = 1; champ <= NF; champ++)
      {
        if ($champ ~ /^\[.*\]$/)
        {
          var = substr($champ, 2, length($champ) - 2)
          if (ENVIRON[var] != "")
          {
            sub(/.*/, ENVIRON[var], $champ)
          }
        }
        printf("%s ", $champ)
      }
      print ""
    }' fichier_entree > fichier_sortie

  11. #11
    DIE
    DIE est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 101
    Par défaut
    Merci de ta patiente et excuse moi pour les problèmes de compréhension

    donnera en fichier de sortie:
    salut ça va jmelyn ? tu es où /local/scratch et ta soeur [COUCOU][/code]Si c'est bien cela, voici une commande awk qui marche.
    en fait non c'était un exemple d'exécution ce que tu me donnes. Le fichier en sortie doit être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    salut ça va ${LOGIN} ? tu es où ${PWD} et ta soeur [COUCOU]
    d'où toujours le soucis de remplacer les crochets [ ] par ${}

  12. #12
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bon, on y arrive semble-t-il. Il suffit alors de changer juste quelques caractères...
    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
    awk '
    {
      for (champ = 1; champ <= NF; champ++)
      {
        if ($champ ~ /^\[.*\]$/)
        {
          var = substr($champ, 2, length($champ) - 2)
          if (ENVIRON[var] != "")
          {
            sub(/.*/, "{"var"}", $champ)
          }
        }
        printf("%s ", $champ)
      }
      print ""
    }' fichier_entree > fichier_sortie
    Edit: Petite erreur dans la modification, j'ai oublié le '$'. Donc la partie rouge devient "${"var"}".

  13. #13
    DIE
    DIE est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 101
    Par défaut
    Oui ta méthode marche bien
    mais j'ai oublié de te préciser que les valeurs entre crochets ne sont pas forcément des champs, il va arriver très souvent que j'ai des données de cette forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Bonjour c'est un [LOGIN][USER][PWD] pour tester [LOGIN][USER], bye

    d'où mon utilisation de while(match.....) au lieu de for(champs...)
    donc j'ai essayé de m'inspirer de ton script qui fonctionne pour faire le mien, et je n'y arrive pas
    ça ne m'affiche pas ce que je souhaite.
    Pourrais tu m'aider de nouveau et m'expliquer mes erreurs ci-desssous

    merci d'avance

    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
     
    #!/usr/bin/awk  -f
     
    BEGIN   {
    #system("cat _var")
    print "\nResultat\n"
            }
     
    $0 !~ /^#/ && $0 !~ /^$/
            {
            while(match($0,/\[[A-Z]*\]/))
                    {
                     var=substr($0,RSTART+1,RLENGTH-2)  # récup variable ex : LOGIN
                     vor=substr($0,RSTART,RLENGTH)   # récup variable complète ex : [LOGIN]
                     if (ENVIRON[var] != "")
                      {
                       sub(/.*/,"${"var"}",vor)
                      }
                    }
                    printf("%s ", vor)
            }

  14. #14
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Plutôt que j'explique ce qui ne marche pas, essaie de comprendre ce qui marche. J'ai bien décomposé chaque étape avec des variables intermédiaires pour que ce soit déchiffrable.
    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
    awk '
    $0 !~ /^$/ && $1 !~ /^#/
    {
      for (start = 1; start <= length(); start = newStart)
      {
        restOfLine = substr($0, start)
        if (match(restOfLine, /\[([[:upper:]]+)\]/, varArray) == 0)
        {
          break
        }
        val = ENVIRON[varArray[1]]
        if (val != "")
        {
          sub(varArray[1], val)
        }
        newStart = varArray[0, "start"] + varArray[0, "length"]
      }
      print
    }' file_in > file_out
    Lis bien le man de awk, notamment pour les commandes length(), match() et sub(). Si tu ne comprends pas certaines choses, pose des questions.

  15. #15
    DIE
    DIE est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    101
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 101
    Par défaut
    ok j'ai bien analysé ton script et j'ai tout compris... enfin je crois car je n'ai pas eu trop le temps de me pencher dessus cette semaine (mon chefaillon m'ayant donné du boulot)

    J'ai hélas encore un plantage sur ton script

    Syntax Error The source line is 8.
    The error context is
    if (match(restOfLine, >>> /\[.*\]/, <<<
    awk: 0602-502 The statement cannot be correctly parsed. The source line is 8.

    En cherchant dans mon bouquin awk et sur google je n'ai vu nulle part la possibilité de mettre le resultat de match dans un tableau (comme varArray dans ton script).
    En cherchant dans ce forum je suis tombé sur ton post où tu parles de cette option :

    http://www.developpez.net/forums/d65...substr-erreur/

    * la fonction match() permet de récupérer plusieurs strings en une seule fois (man awk) en ajoutant une troisième variable (tableau).
    Faut il une version spécial de AWK pour que ça marche ?
    sinon y a-t-il moyen de contourner ? si oui je vais chercher encore

    merci

Discussions similaires

  1. probléme de crochet
    Par <Terry> dans le forum Mac OS X
    Réponses: 5
    Dernier message: 02/08/2011, 20h29
  2. [AWK] débutant et problème
    Par cyrill.gremaud dans le forum Shell et commandes GNU
    Réponses: 2
    Dernier message: 14/12/2010, 17h53
  3. Réponses: 5
    Dernier message: 31/08/2006, 14h34
  4. Commande awk fonction gsub
    Par vbcasimir dans le forum Linux
    Réponses: 1
    Dernier message: 29/05/2006, 12h12
  5. Awk - Utilisation Gsub
    Par lili_bzh dans le forum Linux
    Réponses: 1
    Dernier message: 20/02/2006, 11h35

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