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 :

debutant en perl !


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Novembre 2012
    Messages : 10
    Par défaut debutant en perl !
    Bonjour à tous,

    j'ai besoin de votre aide !

    Voila j'ai 2 fichiers
    fichier 1 :
    84175 2147442987
    84176 2147442988
    84177 2147442989
    84178 2147442990
    84179 2147442991
    84180 2147442992
    84181 2147442993
    ...

    fichier 2 :
    84175 2147442987
    84175 2147445488
    84176 2147442988
    84176 2147445489
    84177 2147442989
    84177 2147445490
    84178 2147442990
    84178 2147445491
    84179 2147442991
    84179 2147445492
    84180 2147442992
    84180 2147445493
    84181 2147442993
    84181 2147445494
    ...

    j'aimerais faire un pg me comparant les 2 fichiers, c'est à dire :
    Si Ligne Fichier1 est dans Fichiers2 OK
    Sinon pas OK...

    un pg existe actuellement mais en shell avec des grep, et c'est hyper long car pas mal de ligne.

    Pourriez vous m'aidez car je n'y connais rien en perl

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2013
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 247
    Par défaut
    Tes lignes sont elles dans le même ordre dans les 2 fichiers (exemple tri numérique, alphabétique...)?

    Si oui: tu lis le fichier 1 et tant que tu trouves pas la ligne dans le fichier 2 tu continues de progresser dans le fichier 2...

    Si non: Le plus simple si tu n'as pas de trop gros fichiers (qu'est ce que tu entends par "pas mal de lignes"?) tu ouvres le plus petit, tu crées un hash dont clé=ligne sans retour charriot
    Quand tu lis le second, tu chercheras hash{'ligneFichier2'} existe: si oui -> ok sinon -> ko

  3. #3
    Membre chevronné 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
    Par défaut
    si tu es sous unix le programme 'join' fait probablement exactement ce que tu veux.

    Sinon c'est un bon exercice et je te conseille d'essayer de programmer par toi même avant de regarder le script ci-dessous.

    Si les fichiers sont triés dans l'ordre lexicographique croissant (ce qui semble être le cas) tu peux lire chaque fichier ligne par ligne : tant qu'elles sont égales c'est OK et on consomme la ligne dans chaque fichier. Si l'une est inférieure, ce n'est pas OK et on va à la ligne suivante dans le même fichier.

    les utilisations de 'defined' ci-dessous permettent de tester si on a épuisé l'un ou l'autre des fichiers. Les fonctions consomme1 et consomme2 ne sont pas indispensables mais elles permettent d'intégrer un garde-fou au cas où les fichiers ne seraient pas triés dans l'ordre lexicographique croissant.

    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
    # compare_sorted.pl
    use strict; 
    use warnings;
     
    {
        my ($fn1, $fn2) = @ARGV;
        open my $i1, "<", $fn1 or die "$fn1: $!";
        open my $i2, "<", $fn2 or die "$fn2: $!";
        my $l1 = <$i1>; # première ligne du premier fichier
        my $l2 = <$i2>; # première ligne du second fichier
        sub consomme1 { # lit dans $l1 une ligne dans le premier fichier et retourne la précédente
    	my $pl1 = $l1;
    	$l1 = <$i1>;
    	die "$fn1 n'est pas trié par ordre lexicographique croissant!"
    	    if defined $l1 && $pl1 gt $l1;
    	$pl1;
        }
        sub consomme2 { # lit dans $l2 une ligne dans le second fichier et retourne la précédente
    	my $pl2 = $l2;
    	$l2 = <$i2>;
    	die "$fn2 n'est pas trié par ordre lexicographique croissant!"
    	    if defined $l2 && $pl2 gt $l2;
    	$pl2;
        }
        while (defined $l1 && defined $l2) {
    	if ($l1 lt $l2) {
    	    print "NOK1\t" . consomme1;
    	} elsif ($l1 eq $l2) {
    	    print "OK\t" . consomme1;
    	    consomme2;
    	} else { # ($l1 gt $l2)
    	    print "NOK2\t" . consomme2;
    	}
        }
        print "NOK1\t" . consomme1 while defined $l1; # purge du premier fichier si le second est épuisé
        print "NOK2\t" . consomme2 while defined $l2; # purge du second fichier si le premier est épuisé
    }
    ce qui donne quelque chose comme

    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
    Taisha:~/tttmp $ perl compare_sorted.pl f1 f2
    OK	84175 2147442987
    NOK2	84175 2147445488
    OK	84176 2147442988
    NOK2	84176 2147445489
    OK	84177 2147442989
    NOK2	84177 2147445490
    OK	84178 2147442990
    NOK2	84178 2147445491
    OK	84179 2147442991
    NOK2	84179 2147445492
    OK	84180 2147442992
    NOK2	84180 2147445493
    OK	84181 2147442993
    NOK2	84181 2147445494
    Taisha:~/tttmp $

  4. #4
    Membre chevronné 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
    Par défaut
    j'ai oublié de dire que le script compare_sorted.pl ci-dessus suppose non seulement que les fichiers sont triés mais en plus que chaque ligne figure au plus une seule fois dans chaque fichier.

  5. #5
    Membre habitué
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Novembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Novembre 2012
    Messages : 10
    Par défaut
    Le 1er fichier comporte 130000 lignes
    Le 2eme fichier comporte 450000 lignes

    j'ai fait ceci :

    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
    my ( $line, $line1, $var, @tab, @words2);
     
    open (FIC1 ,"<gbadoclist.tmp") or die"open: $!";
     
    open (FIC2 ,"<sgmdoclist.tmp") or die"open: $!";
     
    open (FIC3,">desynchro.log") or die "E/S : $!\n";
     
    while ( <FIC2> ) {
     
        push @tab, split;
    }
    my $Taille = @tab;
    while ( $line = <FIC1> ) {  
    @words = split( ' ', $line );
    my $i = 0;
    my $j = 1;
    foreach  ( 0..$Taille) {
     
    	if ($i < $Taille && $j < $Taille) {
     
        		if ( $words[0] != $tab[$i] ) {
     
    			$i = $i+2;
    			$j = $j+2;
     
    		} elsif ( $words[1] != $tab[$j] ) {
     
    			$i = $i+2;
    			$j = $j+2;	
    		} else {
     
    		print "reference $words[0] $words[1] trouveé\n ";
    		last;
            		}
    		}		
    	else {
     
    /**** pour ecrire dans un fichier les lignes qui ne sont pas dans le 2eme fichier ****/
    	my $sortie = select(FIC3);
     
    	print "reference $words[0] non trouveé\n ";
     
    	select($sortie);
     
    	last;
     
    	}		
    }
    }
    close(FIC2);
    close(FIC1);

  6. #6
    Membre chevronné 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
    Par défaut
    Je ne crois pas que ce script fasse ce que tu veux...

    Si tu est pressé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    sort -u gbadoclist.tmp > gbadoclist.sorted
    sort -u sgmdoclist.tmp > sgmdoclist.sorted
    perl compare_sorted.pl gbadoclist.sorted sgmdoclist.sorted | egrep "^NOK1" | sed '1,$s/^NOK1.//g' > desynchro.log
    et compare avec ton résultat.

    Quelques remarques :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    open (FIC1 ,"<gbadoclist.tmp") or die"open: $!";
    ....
    close(FIC1);

    pas optimal pour plusieurs raisons:
    1. plutot que de polluer l'espace de noms global, il est préférable d'utliser des variables pour les handle de fichiers, donc open my $handle, ...
    2. la forme à deux arguments de open est découragée, donc open my $handle, '<', 'gbadoclist.tmp'
    3. le message d'erreur n'est pas explicite (on ne sait pas à quel fichier il se reporte). Il est préférable d'utiliser une variable pour le nom de fichier et de la réutiliser dans le message d'erreur.
    4. dans un petit script comme celui là il n'est pas nécessaire de fermer le fichier; mais si tu le fermes autant signaler une erreur si elle se produit (surtout pour les fichiers ouverts en écriture).


    donc coder plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    my $fn1 = 'gbadoclist.tmp'
    open my $fic1, '>', $fn1 or die "open $fn1: $!"
    ...
    close $fic1 or die "close $fn1: $!";
    si tu ne fermes pas le fichier tu peux utiliser un for :

  7. #7
    Membre chevronné 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
    Par défaut
    oups... fausse manip...

    donc, tu peux utiliser un for :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my $fic1; for ('gbadoclist.tmp') { open($fic1, '>', $_) || die "open $_: $!"}
    c'est affaire de goût...

    ---------------
    Le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while ( <FIC2> ) {
    push @tab, split;
    }
    extrait de chaque ligne de FIC2 des mots séparés par un ou plusieurs espaces, et les empile dans @tab;

    autrement dit, si FIC2 contient
    @tab contient à la fin
    est-ce vraiment ce que tu veux ?

    --------------
    la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @words = split( ' ', $line );
    découpe $line caractère par caractère, pas par mots.

    --------------
    la comparaison
    force un contexte numérique sur ses deux arguments, ce qui n'est probablement âs ce que tu veux (pour comparer des chaines de caractères, utiliser lt, le, eq, ne, gt, ge...).

Discussions similaires

  1. Super lien pour debutant en perl
    Par gool42 dans le forum Langage
    Réponses: 1
    Dernier message: 04/01/2007, 14h59
  2. aide pour debutant en perl
    Par donny dans le forum Langage
    Réponses: 3
    Dernier message: 30/08/2006, 18h13
  3. [Debutant] Module Perl
    Par Luffy Duck dans le forum Modules
    Réponses: 4
    Dernier message: 06/04/2006, 17h25
  4. [langage] Question débutant compilation PERL
    Par sebbyoguard dans le forum Langage
    Réponses: 5
    Dernier message: 04/09/2004, 19h39
  5. [langage] Renseignement pour débuter sur perl
    Par freeshman dans le forum Langage
    Réponses: 2
    Dernier message: 29/04/2004, 23h47

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