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 :

comparer contenu de deux fichiers


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2008
    Messages
    57
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 57
    Points : 20
    Points
    20
    Par défaut comparer contenu de deux fichiers
    Bonjour, je débute en perl, excusez mon peu de connaissances ....

    Voila, j'ai deux fichiers (A & B), je souhaite regarder si chaque ligne du fichier A est présente dans le fichier B, si non, je l'enregistre dans B ...

    Je pensais avoir réussi or, mon programme ne compare pas une ligne (de A) à toutes les autres de B, mais la premiere de A à la première de B, etc ...

    J'ai ensuite pensé créer une liste à partir de mon premier fichier ... mais visiblement c'est un échec aussi ...

  2. #2
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    Un tableau associatif fera certainement l'affaire (si tes fichiers n'ont pas un nombre trop élevé de lignes).

    Quelque chose comme ça:
    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
    #!/usr/bin/env perl
    use strict; use warnings;
     
    my ($fh, %index);
     
    open $fh, '<', 'file1' || die "$!\n";
    while (<$fh>) { $index{$_} = 1; }
    close $fh;
     
    open $fh, '<', 'file2' or die "$!\n";
    while (<$fh>) { $index{$_} = 0; }
    close $fh;
     
    open $fh, '>>', 'file2' or die "$!\n";
    print $fh grep { $index{$_} == 1 } keys %index;

  3. #3
    Membre à l'essai
    Inscrit en
    Juin 2008
    Messages
    57
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 57
    Points : 20
    Points
    20
    Par défaut
    Merci ç'est exactement le résultat auquel je souhaitais arriver, mais pour la méthode je n'aurais jamais fait ça .. j'aimerais bien que tu m'expliques un peu le code histoire de pas l'utiliser sans savoir ce qui se passe derrière ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #!/usr/bin/env perl
    use strict; use warnings;
    Là, ok

    $fh correspond à mon fichier je suppose, mais le %index .. ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open $fh, '<', 'file1' || die "$!\n";
    while (<$fh>) { $index{$_} = 1; }
    close $fh;
    { $index{$_} ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    open $fh, '<', 'file2' or die "$!\n";
    while (<$fh>) { $index{$_} = 0; }
    close $fh;
     
    open $fh, '>>', 'file2' or die "$!\n";
    print $fh grep { $index{$_} == 1 } keys %index;
    la dernière ligne c'est le néant total

  4. #4
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    j'aimerais bien que tu m'expliques un peu le code histoire de pas l'utiliser sans savoir ce qui se passe derrière ...
    Oui, bien sûr.

    my %index; déclare un tableau associatif, c'est à dire une liste non-ordonnée de couples clé-valeur.

    Ensuite comme tu l'as compris, on ouvre le premier fichier en lecture et on lit ligne à ligne. Pour chaque ligne lu (dans $_), on crée une entrée dans notre tableau avec pour clé la dite ligne et pour valeur 1, c'est le $index{$_} = 1;

    On ouvre le second fichier et pour chaque ligne lue, on met l'entrée correspondante dans le tableau à 0, c'est à dire que les lignes déjà lus dans le premier fichier vont se retrouver marquées 0 dans le tableau. En fin de compte n'auront un 1 comme valeur que les clés qui correspondent à des lignes lus dans file1 et absentes de file2.

    Il ne reste plus qu'à écrire les clés du tableau qui ont pour valeur 1. C'est ce que fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print $fh grep { $index{$_} == 1 } keys %index;
    keys %index retourne la liste des clés ("tes lignes") et grep procède chacune des clés (passés comme $_) et filtre celle dont la valeur est 1. grep retourne la liste des clés satisfaisant ce critère. Il ne reste plus qu'à l'écrire dans file2 (ouvert en ajout).

    Voilà tout. N'hésite pas à demander si quelque chose n'est pas clair.

  5. #5
    Membre à l'essai
    Inscrit en
    Juin 2008
    Messages
    57
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 57
    Points : 20
    Points
    20
    Par défaut
    Une chose me perturbe ... dans le premier fichier, on lit chaque ligne, et on y défini la valeur 1 !

    Pour le second fichier c'est exactement la même syntaxe, comment sait-il qu'il l'a déjà lu ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open $fh, '<', 'file2' or die "$!\n";
    while (<$fh>) { $index{$_} = 0; } ### Tant que je retrouve la ligne, je la passe à 0, c'est comme ça qu'il faut que je le comprenne ? :oops:
    close $fh;

  6. #6
    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
    Il ne le sait pas, il met donc toutes les lignes de B dans %index avec une valeur de 0. Un raffinement serait donc de tester avant insertion si la ligne était déjà là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    open $fh, '<', 'file2' or die "$!\n";
    while (<$fh>) { $index{$_} = 0 if exists $index{$_}; } 
    close $fh;
    Ca ne change pas la complexité totale du code O(n+m) (n lignes dans A, m lignes dans B) mais ça économise un peu sur la consommation mémoire au cas où B est beaucoup plus gros que A et peut donc avoir des effets bénéfiques à la fois sur la vitesse et l'occupation mémoire du programme.

    --
    Jedaï

Discussions similaires

  1. Comparer contenu de deux fichiers
    Par Garkan dans le forum Shell et commandes GNU
    Réponses: 3
    Dernier message: 08/07/2013, 10h10
  2. Comparer contenu de 2 fichiers
    Par Raikyn dans le forum Débuter
    Réponses: 14
    Dernier message: 10/03/2013, 22h27
  3. parser le contenu de deux fichiers XML
    Par getrude dans le forum XSL/XSLT/XPATH
    Réponses: 28
    Dernier message: 07/03/2012, 18h22
  4. Réponses: 0
    Dernier message: 14/11/2010, 15h22
  5. Comparer le contenu de deux fichiers
    Par Sancti_Eyes dans le forum Langage
    Réponses: 7
    Dernier message: 03/05/2009, 10h54

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