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

Langage Perl Discussion :

Extraction des données


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut Extraction des données
    salut,
    je parcours un fichier, écrit de la manière suivante:

    PORTE a,b,c,d,e,f,g,
    h,i,j,k,


    je dois afficher:
    a PORTE
    b PORTE
    c PORTE
    d PORTE
    e PORTE
    f PORTE
    g PORTE
    ....

    comment je vais faire?
    merci

  2. #2
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par bezoindaidde
    salut,
    je parcours un fichier, écrit de la manière suivante:

    PORTE a,b,c,d,e,f,g,
    h,i,j,k,


    je dois afficher:
    a PORTE
    b PORTE
    c PORTE
    d PORTE
    e PORTE
    f PORTE
    g PORTE
    ....

    comment je vais faire?
    merci
    Bonne question ! Comment vas-tu faire ?

    Tu vas lire le fichier et le parser.

    Par exemple :
    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
    #!/usr/bin/env perl
    use strict; use warnings;
     
    my $filename = shift;
    open my($data_src), '<', $filename
      or die "Couldn't open $filename : $!\n";
     
    while( <$data_src> ){
      my( $nature, $list ) = m/^(\w+)\s+(.+)$/;
      my @list = split /,/, $list;
      print "$_ $nature\n" for @list;
    }
     
    close $data_src;
     
    __END__
    Ou quelque chose comme ça. (à vrai dire, s'il y a vraiment des sauts de ligne en plein dans ta liste comme dans ton exemple, ça va être un peu plus compliqué)

    --
    Jedaï

  3. #3
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    veux tu bien m'expliquer le code??
    g du mal à le comprendre le principe...c'est quoi shift, > ...etc?

  4. #4
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    my( $nature, $list ) = m/^(\w+)\s+(.+)$/; ????

    excuse moi, c'est que du perl ??

  5. #5
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    J'utilise un certain nombre d'idiômes dans mon script, néanmoins rien d'affolant. Par exemple quand tu vois une fonction que tu ne connais pas "shift" ici, tu devrais avoir le réflexe de regarder sa documentation (en tapant "perldoc -f shift" dans une console, ou en consultant le site perldoc, ou la traduction partielle en français). Tu as alors ta réponse (ou pas, selon ton expérience de programmateur...) :
    Retourne la première valeur d'un tableau après l'avoir supprimée du tableau en rétrécissant sa taille de 1 et en déplaçant tout vers le bas. Renvoie undef si il n'y a pas d'éléments dans le tableau. Si TABLEAU est omis, shift agira soit sur le tableau @_ s'il est dans la portée lexicale d'une subroutine ou d'un format, soit sur le tableau @ARGV s'il est dans la portée lexicale d'un fichier
    @ARGV est un nom très souvent utilisé (dans beaucoup de langages) pour le tableau des arguments de la ligne de commande. Autrement dit, mon "shift" ici récupère le premier argument de mon programme.

    Quant à tes autres questions, malheureusement "..." n'est pas suffisamment expressif pour que je comprenne ce qu'elles sont...


    Citation Envoyé par bezoindaidde
    my( $nature, $list ) = m/^(\w+)\s+(.+)$/; ????

    excuse moi, c'est que du perl ??
    Et bien dire qu'il ne s'agit que de Perl serait légèrement polémique : en effet la partie m/.../ est écrite dans le langage des regex (expressions régulières), qui permet de parser (c'est à dire décomposer en éléments lexicaux) facilement des expressions simples sous formes de chaînes de caractères. Les regex sont très utilisées en Perl car elles y sont très faciles d'emploi (bien plus que dans la plupart des langages qui permettent leur utilisation).

    Une version légèrement retouchée de mon script, avec commentaires à la clé :

    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
    26
    27
    28
    29
    #!/usr/bin/env perl
    use strict; use warnings;
     
    # récupérer le premier argument du script
    # on suppose qu'il s'agit du nom du fichier à traiter
    my $filename = $ARGV[0];
     
    # on ouvre le fichier en lecture ('<'), le handle de fichier est $data_src
    open my($data_src), '<', $filename
      or die "Couldn't open $filename : $!\n";
     
    # boucle de lecture, on lit ligne par ligne dans $line
    while( my $line = <$data_src> ){
      # on extrait "PORTE" dans $nature et la liste dans $list_string
      my( $nature, $list_string ) = ($line =~ m/^(\w+)\s+(.+)$/);
      # on découpe notre liste selon les virgules et on place ses éléments
      # dans le tableau @list
      my @list = split /,/, $list_string;
      # on itère sur les éléments de @list en les plaçant tour à tour dans $object
      for my $object ( @list ){
        # on fait l'affichage tel que tu l'as indiqué
        print "$object $nature\n";
      }
    }
     
    # on referme le fichier
    close $data_src;
     
    __END__
    Ca va mieux comme ça ? Néanmoins dis-toi bien qu'on ne prendra pas toujours le temps de te faire un joli code commenté de bout en bout comme celui-ci, il va falloir apprendre un peu les bases de la programmation en Perl pour pouvoir lire un code basique comme une ouverture de fichier suivi d'une lecture et décomposition avec regex, c'est le schéma de base de beaucoup de programmes après tout (Perl est très utilisé pour faire du traitement ou du filtrage de données, texte ou binaires).

    --
    Jedaï

  6. #6
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    merci pr l'effort !

  7. #7
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    g compris le code, ça marche bien mais que pour une ligne, il m'affiche pas le reste:
    par exple:

    PORTE a,b,c,d,e,f,g,
    h,i,j,k,

    il affiche:

    a PORTE
    b PORTE
    c PORTE
    d PORTE
    e PORTE
    f PORTE
    g PORTE

    mais ne m'affiche pas:

    h PORTE
    i PORTE
    j PORTE
    k PORTE

    est ce que vous avez une idée??

    (j'ai pensé à raisonner par rapport à la virgule, mais il se peut que dans ma ligne j'ai des données qui ne correspondent pas à PORTE, néanmoins la ligne contient des virgules..)

  8. #8
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Alors on complique un peu la boucle de lecture :
    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/env perl
    use strict;
    use warnings;
     
    my $filename = shift;
    open my ($data_src), '<', $filename
      or die "Couldn't open $filename : $!\n";
     
    my($nature, $list);
    while (<$data_src>) {
        chomp;
        if ( m/^(\w+)\s+([^\s]+)$/ ) {
            ( $nature, $list ) = ( $1, $2 );
            my @list = split /,/, $list;
            print "$_ $nature\n" for @list;
        }
        else {
            my @list = split /,/;
            print "$_ $nature\n" for @list;
        }
    }
     
    close $data_src;
     
    __END__
    --
    Jedaï

  9. #9
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    bon j'essaie de comprendre ton programme, aprés de petites modifs pr l'adapter à mon texte, je le compile et ça marche.
    seulement kan je fais:
    @array = <$data_src>;
    et j'initialise un compteur : $cpt =0;
    en faisant:

    while ($array[$cpt])

    if ($array[$cpt]=~ m/^(\w+)\s+([^\s]+)$/ ) (pour raisonner par rapport à chaque ligne de mon fichier, car j'en ai plusieurs)

    dans ce cas là, je comprends pas, je retrouve le même prob qu'avant, il prend en compte que la ligne elle même : (PORTE a,b,c,d,)
    pour l'autre cas (else) ca ne marche pas.

    est ce que c différent de ce que lorsqu'on met:
    while (<$data_src>) ????

  10. #10
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    parce que finalement je dois traiter mon fichier ligne par ligne en ayant comme mot clé ORTE.
    car je dois traiter le cas de PORTE, PORTE 1, PORTE 2.... ça dépend des cas.

    j'espère que je me suis faite comprise.

    j'atten ton feed back.
    merci

  11. #11
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par bezoindaidde
    j'espère que je me suis faite comprise.
    Non, tu ne t'es pas vraiment faite comprendre, désolé mais il va me falloir un échantillon plus vaste des données en entrée pour pouvoir donner une réponse plus précise. De ce que j'en avais compris, mon script fonctionnait parfaitement mais bien sûr ton exemple était extrèmement sommaire...

    ??
    C'est quoi ça ? Pourquoi tu préfères lire l'intégralité du fichier puis le traiter ligne par ligne au lieu de simplement lire ligne par ligne ? Par ailleurs pour parcourir un tableau en Perl, on utilise pas vraiment un compteur avec une boucle while (mais sur quoi porte donc ton test s'il ne porte pas sur le compteur ??), mais plutôt la boucle for (parfois écrite foreach, mais les deux appellations sont synonymes).

    --
    Jedaï

  12. #12
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    d'accord, je vais essayer de te donner un exemple encore plus concret:

    dans mon fichier qui est énorme: (il y a énormèment de modules)
    voici le bloc qui m'intéresse:

    module portes (a,b,c,d,e,f,g,h,i,
    j,k,l,m,n,o,p,q,u,r,s);
    PORTE a;
    PORTE1 b,c,d,e,f;
    PORTE2 g;
    test [0:1]
    PORTE1 i,j,k,l,
    p,d,a,u,r,s;
    .
    .
    .
    endmodule

    l'objectif est de parcourir mon fichier ligne par ligne, une fois je retrouve la ligne : module portes, je vois ce qui est aprés, à chaque fois que j'ai PORTE, ou PORTE1, ou PORTE2, je dois afficher les données comme je l'ai expliqué avant.
    notamment pour cet exemple, je dois afficher:
    a PORTE
    b PORTE1
    c PORTE1
    d PORTE1
    e PORTE1
    f PORTE1
    g PORTE2
    i PORTE1
    j PORTE1
    l PORTE1
    p PORTE1
    d PORTE1
    a PORTE1
    u PORTE1
    r PORTE1
    s PORTE1


    voilà donc pourquoi à l'intérieur du if, que t'as déja écrit dans ton script, je suppose qu'il faudra que je mette aussi une condition genre:
    if ($array[$cpt]= ~/PORTE1/) par exple qd il s'agit de PORTE1.

  13. #13
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par bezoindaidde
    voilà donc pourquoi à l'intérieur du if, que t'as déja écrit dans ton script, je suppose qu'il faudra que je mette aussi une condition genre:
    if ($array[$cpt]= ~/PORTE1/) par exple qd il s'agit de PORTE1.
    Pourquoi voudrait-on individualiser le cas de PORTE1 ou de PORTE2 plus qu'un autre ? Non, ces cas là sont déjà traités correctement, les seuls problèmes que peuvent poser ton fichier ce sont les types de lignes que tu n'avais pas mis dans ton exemple (module, endmodule et test) et le fait que les lignes se finissent par des point-virgules ce que tu avais également oublié... "Garbage in, garbage out" disent les anglais : si tu ne nous donnes pas les données correctes, nous ne risquons pas de te donner des réponses correctes.

    Essayons encore, néanmoins je doute que ton nouvel exemple soit plus exhaustif que le précédent...
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #!/usr/bin/env perl
    use strict;
    use warnings;
     
    my $filename = shift;
    open my ($data_src), '<', $filename
      or die "Couldn't open $filename : $!\n";
     
    my ( $module, $in_list_to_print, $nature, $list );
    while (<$data_src>) {
        chomp;
        if (m/^module \s+ (\w+) \s* \( ([a-z,]*) (?:\);)? \s* $/x) {
            $module           = $1;
            $in_list_to_print = 0;    # peut-être à étendre plus tard ?
        }
        elsif (m/^endmodule \s* $/x) {
            undef $module;
        }
        elsif (m/^test \s+ (\[.*?\]) .* $/x) {
            $in_list_to_print = 0;    # idem ?
        }
        elsif (m/^(\w+) \s+ ([a-z,]+) ;? \s* $/x) {
            ( $nature, $list ) = ( $1, $2 );
            my @list = split /,/, $list;
            print "$_ $nature\n" for @list;
            $in_list_to_print = 1;
        }
        elsif ( $in_list_to_print and m/^([a-z,]+) ;? \s* $/x ) {
            my @list = split /,/, $1;
            print "$_ $nature\n" for @list;
        }
    }
     
    close $data_src;
     
    __END__
    Je ne t'aiderais pas plus loin, essaie de comprendre ce que je fais (je mimique une petite machine à état), d'apprendre les regexs, et d'étendre le script si nécessaire. Mais sans en bouleverser la structure comme avec ton tableau, ça ne devrait pas être nécessaire (et peu recommandable si tes fichiers sont vraiment gros...).

    --
    Jedaï

  14. #14
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    je te remercie, je lirais ton code, et j'essaierais de le comprendre.

  15. #15
    Membre à l'essai
    Inscrit en
    Juillet 2006
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 52
    Points : 17
    Points
    17
    Par défaut
    le prob que je trouve dans ton code, c'est qu'il me prend tous les modules qui existent dans mon fichier et m'affiche le contenu, alors que ce qui m'intéresse c juste le module portes. je vois pas ou est ce que je dois lui mettre la condition, pour qu'il ne me fasse le traitement que sur le module portes.
    genre
    while ($ligne = ~/portes\s+/) ou un truc comme ça, surout au niveau des regex que t'as mis.
    là par exple :

    if ($ligne =~ /^module \s+ (\w+) \s* \( ([a-z,]*) (?:\)? \s* $/x)

    je la modifie en mettant:

    if ($ligne =~ /^module \s+ (\portes) \s* \( ([a-z,]*) (?:\)? \s* $/x)
    ou
    if ($ligne =~ /^module \s+ portes \s* \( ([a-z,]*) (?:\)? \s* $/x)
    les deux ne marchent pas.

    je sais que j'ai abusé, mais chui débutant en perl, encore un coup de pouce sur ce point, et je n'en ajouterais pas !

  16. #16
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    D'accord je vois, dans ce cas la modification à apporter est en fait minime, toute l'infrastructure est déjà en place, il faut juste vérifier qu'on est bien dans le module "portes" avant d'afficher :
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #!/usr/bin/env perl
    use strict;
    use warnings;
     
    my $filename = shift;
    open my ($data_src), '<', $filename
      or die "Couldn't open $filename : $!\n";
     
    my ( $module, $in_list_to_print, $nature, $list );
    while (<$data_src>) {
        chomp;
        if (m/^module \s+ (\w+) \s* \( ([a-z,]*) (?:\);)? \s* $/x) {
            $module           = $1;
            $in_list_to_print = 0;    # peut-être à étendre plus tard ?
        }
        elsif (m/^endmodule \s* $/x) {
            $module = '';
            $in_list_to_print = 0; 
        }
        elsif (m/^test \s+ (\[.*?\]) .* $/x) {
            $in_list_to_print = 0;    # idem ?
        }
        elsif ( $module eq 'portes' and m/^(\w+) \s+ ([a-z,]+) ;? \s* $/x ) {
            ( $nature, $list ) = ( $1, $2 );
            my @list = split /,/, $list;
            print "$_ $nature\n" for @list;
            $in_list_to_print = 1;
        }
        elsif ( $in_list_to_print and m/^([a-z,]+) ;? \s* $/x ) {
            my @list = split /,/, $1;
            print "$_ $nature\n" for @list;
        }
    }
     
    close $data_src;
     
    __END__
    --
    Jedaï

Discussions similaires

  1. [RSS] extraction des données d'un flux
    Par toddy_101 dans le forum APIs
    Réponses: 4
    Dernier message: 23/02/2007, 17h28
  2. vc++(6)+extraction des données dans une image(.tif)
    Par spootnic22 dans le forum Visual C++
    Réponses: 1
    Dernier message: 22/11/2006, 16h14
  3. [MySQL] Problème de Charset à l'extraction des données
    Par naoufal01 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 06/11/2006, 13h14
  4. extraction des données dans une table Access
    Par moabomotal dans le forum Access
    Réponses: 2
    Dernier message: 26/05/2006, 11h17

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