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 :

comparaison d'un motif sur la ligne i et la ligne i+1


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Femme Profil pro
    information manager
    Inscrit en
    Janvier 2018
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : information manager

    Informations forums :
    Inscription : Janvier 2018
    Messages : 24
    Points : 18
    Points
    18
    Par défaut comparaison d'un motif sur la ligne i et la ligne i+1
    Bonjour,

    J'ai un fichier texte de plus de 2 millions de lignes. Chaque ligne débute par un identifiant qui est le même sur des centaines de lignes puis change et est à nouveau le même sur des centaines de lignes etc...
    Cet identifiant correspond au motif suivant : ^\d{3}.
    La logique du script : si l'identifiant de la ligne i est différent de celui de la ligne i+ 1 alors PRINT dans un autre fichier la ligne i et la ligne i+1.
    Est ce que qqn peut m'aider à avancer dans ce script ? Je l'ai fait en VBA mais Perl je patauge....

    Merci d'avance

    H.
    Fichiers attachés Fichiers attachés

  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonjour Astrid,

    ce script Perl à la ligne de commande bash devrait t'aider:

    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
     
    $ echo '
    > 101,"Cinta de Moebio","","0717-554X"," ","2","1997",10100208
    > 101,"Cinta de Moebio","","0717-554X"," ","1","1997",10100101
    > 101,"Cinta de Moebio","","0717-554X"," ","1","1997",10100102
    > 101,"Cinta de Moebio","","0717-554X"," ","1","1997",10100103
    > 101,"Cinta de Moebio","","0717-554X"," ","1","1997",10100104
    > 101,"Cinta de Moebio","","0717-554X"," ","2","1997",10100210
    > 102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202504
    > 102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202505
    > 102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202506
    > 102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202507
    > 102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202508
    > 105,"Convergencia. Revista de Ciencias Sociales","1405-1435","2448-5799","11","36","2004",10503605
    > '   | perl -we '
    > my $previous_line = ""; my $prev_id = "";
    > while (<>) {
    > next unless /\w/; # skipping empty lines
    > $id = $1 if /^(\d{3})/;
    > print $previous_line, $_ if $id ne $prev_id;
    > $previous_line = $_; $prev_id = $id;}
    > '
    101,"Cinta de Moebio","","0717-554X"," ","2","1997",10100208
    101,"Cinta de Moebio","","0717-554X"," ","2","1997",10100210
    102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202504
    102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202508
    105,"Convergencia. Revista de Ciencias Sociales","1405-1435","2448-5799","11","36","2004",10503605

  3. #3
    Membre habitué
    Homme Profil pro
    Master Data Manager
    Inscrit en
    Février 2017
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Master Data Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2017
    Messages : 113
    Points : 148
    Points
    148
    Par défaut
    Bonjour astrid123

    Je ne suis pas sûr de bien comprendre le besoin.

    Vous souhaitez récupérer seulement les lignes avant et après changement de l'id ou dispatcher les id dans les fichiers séparés ?

    Quel est le résultat attendu avec votre fichier d'exemple ?

  4. #4
    Membre à l'essai
    Femme Profil pro
    information manager
    Inscrit en
    Janvier 2018
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : information manager

    Informations forums :
    Inscription : Janvier 2018
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Bonjour,

    @ Puppet_Master : Vous souhaitez récupérer seulement les lignes avant et après changement de l'id ou dispatcher les id dans les fichiers séparés ?

    Quel est le résultat attendu avec votre fichier d'exemple ?

    Oui je ne souhaite que récupérer les lignes avant et après changement de l'id.

    Merci d'avance pour votre aide.

    @Lola : merci pour votre code. Je n'ai pas encore eu le temps de le tester.
    Je ne comprends pas bien pourquoi déclarer les variables my $previous_line et my $prev_id comme étant = ""
    Est ce que je peux utiliser la partie perl dans un fichier .pl sans passer par l'intro en bash ?
    Désolée pour ces questions "bêtes".

    H.

  5. #5
    Membre habitué
    Homme Profil pro
    Master Data Manager
    Inscrit en
    Février 2017
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Master Data Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2017
    Messages : 113
    Points : 148
    Points
    148
    Par défaut
    Bonjour astrid123

    voici un script qui devrait vous aider:

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    use strict;
    use warnings;
     
    use File::Slurp qw( write_file read_file );
     
    # fichier source
    my $input_file = 'mon_fichier_source.txt';
     
    # variables de travail
    my $id    = undef;
    my $pline = undef;
    my @csv   = undef;
    my $count = 0;
     
    # stokage du fichier dans un tableau @data ( attention aux problemes de memoire )
    my @data = read_file( $input_file );
     
    # boucle sur les ligne du tableau @data
    foreach my $i ( @data )
    {
        # compteur
        $count++;
     
        # collecte de l'id
        my $new_id = undef();
        if ( $i =~ /^(\d{3})/ )
        {
            $new_id = $1;
        }
        else
        {
            # passe au suivant si pas derniere ligne de @data
            next unless ( $count == $#data );
        }
     
        if ( defined $new_id )
        {
            # definition de $id si 1er id
            $id = $new_id if ( not defined $id );
        }
     
        # compare id et id-1
        unless ( $new_id eq $id )
        {
            # ajout la ligne au tabeau @csv si id = id-1
            push @csv, $pline;
            push @csv, $i;
        }
     
        # ecriture de @csv dans le cas de la derniere ligne de @data
        write_file( "fichier_filtre.csv", @csv) if ( $count == $#data );
     
        # recup id et ligne
        $id = $new_id;
        $pline = $i;
    }
    crée un fichier contenant ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    101,"Cinta de Moebio","","0717-554X"," ","2","1997",10100210
    102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202506
    102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202506
    105,"Convergencia. Revista de Ciencias Sociales","1405-1435","2448-5799","11","36","2004",10503605
    Il y a sûrement des moyens plus efficaces pour résoudre votre problème surtout si vous avez des fichiers vraiment volumineux.

    EDIT:

    L'utilisation du module File::Slurp est surtout une question de confort et pourrait être remplacé par des fonctions natives du langage Perl.

  6. #6
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par astrid123 Voir le message

    @Lola : merci pour votre code. Je n'ai pas encore eu le temps de le tester.
    Je ne comprends pas bien pourquoi déclarer les variables my $previous_line et my $prev_id comme étant = ""
    Le seul but est de la définir, pour éviter d'avoir des warnings intempestifs ("Use of uninitialized value ...") à la ligne 20, quand on va imprimer $previous_line et quand on va comparer pour la première fois $if à $prev_id.

    Citation Envoyé par astrid123 Voir le message
    Est ce que je peux utiliser la partie perl dans un fichier .pl sans passer par l'intro en bash ?
    Oui, il faut juste ajouter le code pour ouvrir et lire le fichier de données en entrée.

  7. #7
    Membre à l'essai
    Femme Profil pro
    information manager
    Inscrit en
    Janvier 2018
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : information manager

    Informations forums :
    Inscription : Janvier 2018
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Bonjour Lolo,

    Je viens de tester le code que vous m'aviez donné en l'intégrant dans un code perl :

    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
    #!/usr/bin/env perl
     
    use strict;
    use warnings;
    my $fic='/home/helene/Bureau/exemple1.txt';
    my $sel='/home/helene/Bureau/fichiersortie.txt';
     
    open my $FILE, "<" , $fic or die "Ouverture impossible de $fic $!";
    open my $FICHIER,">", $sel;
    my $id;
    my $previous_line = ""; my $prev_id = "";
    while (<$FILE>) {
    next unless /\w/; # skipping empty lines
    $id = $1 if /^(\d{3})/;
    print $FICHIER $previous_line, $_ if $id ne $prev_id;
    $previous_line = $_; $prev_id = $id;}
     
    close $FILE;
    close $FICHIER;
    mais j'obtiens une erreur de compilation:

    Use of uninitialized value $id in string ne at nouveauscript.pl line 15, <$FILE> line 1.
    Use of uninitialized value $prev_id in string ne at nouveauscript.pl line 15, <$FILE> line 1.
    Use of uninitialized value $prev_id in string ne at nouveauscript.pl line 15, <$FILE> line 2.

    Que dois-je modifier pour que cela marche ?

    Merci d'avance,

    H.

  8. #8
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Bonsoir Astrid,

    ce ne sont pas des erreurs de compilation, mais des avertissements d'exécution. La différence est très importante : ton script compile correctement, mais rencontre des problèmes d'exécution en fonction des données en entrée (c'est-à-dire du fichier que tu lis). D'ailleurs, il se peut que ton résultat soit correct malgré ces avertissements (mais, même dans ce cas, cela ne veut pas dire qu'il faille ne rien faire, je ne garde jamais tel quel un problème générant ce genre de warning, même si le fichier généré est correct).

    Il faudrait que tu nous donnes le début (les premières lignes) de ton fichier, car il est probable, au vu du warning généré, que la première ligne de ton fichier ne contient aucun groupe de trois chiffres et, donc, que la regex /^(\d{3})/ échoue dans le cas de la première ligne de ton fichier. Peut-être une ligne d'entête ou quelque chose dans ce genre.

  9. #9
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Re-bonsoir Astrid,

    je viens de regarder le fichier joint à ton premier post, et, oui, je confirme, le warning est dû au fait que la première ligne est une ligne d'entête non reconnue par la regex.

    Il suffit très probablement de lire la ligne d'entête (sans en faire quoi que ce soit), avant de commencer la boucle while, par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    open my $FILE, "<" , $fic or die "Ouverture impossible de $fic $!";
    open my $FICHIER,">", $sel;
    my $id;
    my $previous_line = ""; my $prev_id = "";
    my $line = <$FILE>;
    while (<$FILE>) {

  10. #10
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    En uniligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ perl -nE 'print, $tag = $1 if m/^(\d{3})/ && $1 ne $tag' exemple.txt
    101,"Cinta de Moebio","","0717-554X"," ","2","1997",10100208
    102,"Región y Sociedad","1870-3925","2448-4849","XIV","25","2002",10202506
    105,"Convergencia. Revista de Ciencias Sociales","1405-1435","2448-5799","11","36","2004",10503605
    $
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

Discussions similaires

  1. Comparaison valeurs colonne fixes sur 2 lignes variables
    Par y.zehouani dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 18/04/2018, 15h01
  2. [XL-2007] comparaison cellule date sur même ligne et MFC
    Par karlgina dans le forum Excel
    Réponses: 4
    Dernier message: 02/09/2016, 12h47
  3. Comparaison deux cellules d'une même ligne sur une boucle d'une plage
    Par Hocked dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 08/09/2015, 13h51
  4. Réponses: 1
    Dernier message: 13/11/2012, 17h31
  5. [RegEx] Détecter un motif sur plusieurs lignes
    Par dev197 dans le forum Langage
    Réponses: 20
    Dernier message: 02/10/2009, 17h09

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