Forum Programmation.shell Récupérer des infos d'un fichier : parser.

Posté par .
Tags :
1
9
mai
2011

Bonjour à tous,

Je cherche à parser des fichiers dont voici un exemple :

{"tags":0,"flags":0,"change_date":1304607853,"unread":0,"index_id":0,"type":6,"imap_id":285,"date":1304607853,"Path":"/Contacts/","size":0,"sender":"Jean, Jean","id":285,"Ver":10,"folder_id":7,"FlagStr":"","volume_id":0,"TagStr":"","mod_metadata":276,"mod_content":276,"TagNames":"","parent_id":-1,"metadata":"d3:fldd5:email15:jean@reseau.loc9:firstName4:Jean8:homeCity5:Nancy11:homeCountry6:France9:homeState5:5400010:homeStreet21:2à rue de truc machin10:imAddress120:other://jean@msn.com8:lastName4:Jean11:mobilePhone10:0383741751e1:vi10ee"}

Comme vous pouvez le constater, ce fichier est contenu sur une ligne. C'est un fichier caractérisant un "contact" nommé "Jean Jean".

Je cherches à extraire certaines infos. Par exemple, j'aurais voulu récupérer le contenu de "sender", qui est "Jean, Jean", ou encore le "email15", "jean@reseau.loc".

Avez-vous des pistes à me donner ? Je pourrais utiliser Sed, mais bon... Une idée, un conseil ?

Je précises que je travailles dans un fichier Bash, donc son utilisation est obligatoire, pas de Python ou de Ruby ;) .

Bonne journée et merci :) .

  • # C'est du json

    Posté par . Évalué à 4.

    Ton fichier c'est du format json, il existe des module pour les langages que tu ne veux pas utiliser, sinon un google bash script json fonctionne pas trop mal.

    Allez tous vous faire spéculer.

    • [^] # Re: C'est du json

      Posté par . Évalué à 2.

      heu non pas trop, puisque le premier résultat qu'affiche google est justement cette entrée de forum, infinite loop toussa

  • # jsawk

    Posté par (page perso) . Évalué à 1.

    Tu peux essayer d'utiliser jsawk...
    Ou alors en utilisant python
    Et surement dans plein d'autres langages...

  • # Penser unix

    Posté par (page perso) . Évalué à 8.

    Je précises que je travailles dans un fichier Bash, donc son utilisation est obligatoire, pas de Python ou de Ruby ;)

    Tu peux écrire un court programme dans le langage de ton choix qui fait le traitement dont tu as besoin sur ton fichier et écrit la réponse sur la sortie standard. Ensuite tu utilises ton court programme dans ton script bash.

    C'est a ça que sert le shell et c'est la base du travail avec un système Unix.

  • # awk est ton ami

    Posté par . Évalué à 4.

    Si tu n'as pas la possibilité (le droit) d'utiliser autre chose que le shell, utilise awk.

    Tu définis la virgule comme séparateur de champs (variable FS dans awk). Pour le reste ce n'est pas compliqué jusqu'à "metadata" qui peut se traiter avec un poeu de code.

    Un début de code, en supposant que le contenu se trouve dans toto.txt :

    awk -F"," '{for (i=1;i<=NF;i++) {
    split($i,tab,":")
    value=substr($i,length(tab[1])+2)
    hash[tab[1]]=value
    }
    }
    END {
    for (key in hash) {
    print "Key: " key ", value : " hash[key]
    }
    } ' toto.txt`

    Ensuite selon ton besoin, à toi d'adapter le code pour remonter les infos qui t'intéressent.

    Ah, au fait je n'ai pas supprimé les '{ }' dans le résultat, à toi de le faire (en awk de préférence).

    • [^] # Re: awk est ton ami

      Posté par . Évalué à 1.

      Syntaxe wiki dee Mxxxx

      awk -F"," '{for (i=1;i<=NF;i++) {
      #print("i: " i " Value : " $i)
      split($i,tab,":")
      #print "Key: " tab[1]

          value=substr($i,length(tab[1])+2)
          #print ("Value: " value)
          hash[tab[1]]=value
      

      }
      }
      END {
      for (key in hash) {
      print "Key: " key ", value : " hash[key]
      }
      } ' toto.txt

      • [^] # Re: awk est ton ami

        Posté par . Évalué à 2.

        GRRR !!!

        Je recommence :
        awk -F"," '{for (i=1;i<=NF;i++) {
        split($i,tab,":")
        value=substr($i,length(tab[1])+2)
        hash[tab[1]]=value
        }
        }
        END {
        for (key in hash) {
        print "Key: " key ", value : " hash[key]
        }
        } ' toto.txt

        J'ai juste viré les lignes commencant par "#" qui sont des commentaires.

    • [^] # Re: awk est ton ami

      Posté par (page perso) . Évalué à 4.

      Tu définis la virgule comme séparateur de champs (variable FS dans awk)

      Petit farceur, tu devrais lui dire à l'OP que si un champ contient une virgule tout se casse la gueule.

      • [^] # Re: awk est ton ami

        Posté par . Évalué à 3.

        effectivement ça plante si par exemple l'utilisatrice indique pour son nom : "Zézette, épouse X"

        Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

        • [^] # Re: awk est ton ami

          Posté par (page perso) . Évalué à 2.

          si par exemple l'utilisatrice indique pour son nom : "Zézette, épouse X"

          Plus banalement, je pensais à l'adresse postale.

  • # avec sed

    Posté par . Évalué à 2.

    bon c'est du brut de fonderie (ie pas testé j'ai pas de bash sous la main ;) ):

    sed -r 's/\{|,"(\[^"]+\)":/\n\1=/g;s/\}$//' > /tmp/pikaplop
    . /tmp/pikaplop
    echo $tags
    echo $flags
    

    pour le fichier temporaire, il est possible d'utiliser un mktemp ou équivalent.

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

  • # Jsawk

    Posté par . Évalué à 0.

    Salut à tous,

    Bon finalement, j'utilise JsAwk, mais j'ai un short soucis.

    Pour récupérer le "sender", je fais un "jsawk 'return this.sender", qui me renvoie bien "Jean, Jean".

    En revanche, je cherches à récupérer l'email dans les metadata.

    Si je fais un "jsawk 'return this.metadata', il me renvoie tout le contenu des metadata.

    Comment récupérer l'email par exemple ? Je peux même pas me baser sur awk pour séparer par des ":", puisque le contenu peut changer et je n'aurais plus le bon élément...

    Une idée ?

  • # D'un Z qui veut dire Zorroooooo!!!

    Posté par . Évalué à 2.

    C'est con que tu te restreignes à bash... si tu avais choisi un shell normal tu aurais fait ça les doigts dans le nez!

    Petit exemple avec un shell dont la première lettre est la dernière de l'alphabet:

    On va dire que ton fichier est "t" et contient la chaine exact au dessus. Déja, on fait un coup de tr pour avoir la bonne syntaxe :
    aa=($(tr "{},:" " " < t))

    Hop, on met ça dans un tableau. (Il y aurait moyen d'utiliser un tableau associatif mais j'ai pas réussi) :
    bb=${(z)aa}

    On veut un champ? On cherche l'index de la clef, et on a la valeur au champ + 1 :
    print $bb[(($bb[(i)"sender"]+1))]
    "Jean Jean"

    Dégageons ces guillements :
    print ${(Q)bb[(($bb[(i)"sender"]+1))]}
    Jean Jean

    La clé "metadata" est particulière, il faut refaire le même traitement récursivement :
    md=(${(Qz)bb[(($bb[(i)"metadata"]+1))]})

    Et on récupère le champ de la même manière :
    print $md[(($md[(i)email15]+1))]
    jean@reseau.loc9

    Bluffant, non? Et le tout avec une syntaxe super claire! (bon ok je sors... et avant de sortir, j'avoue que ça déconne un peu du coté de homeStreet21 à cause des espaces... mais avec les bons flags il est peut être possible de corriger ça)

Suivre le flux des commentaires

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