Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1441 connectés 

  FORUM HardWare.fr
  Programmation
  Perl

  [Perl] Arrêt traitement si doublons dans champ d'un fichier

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Perl] Arrêt traitement si doublons dans champ d'un fichier

n°2295670
web_olivie​r
R1 Powaaaaa
Posté le 02-02-2017 à 17:02:22  profilanswer
 

Bonjour,
 
Je m'arrache les cheveux sur mon problème.
 
J'ai bien essayé d'adapter la solution du topic : http://forum.hardware.fr/hfr/Progr [...] 5185_1.htm mais je n'y arrive pas.
 
Voila mon problème.
 
J'ai un fichier sous la forme :
 
cmd1 param1 valeur1
cmd2 param2 valeur2
...
 
Les champs cmd et valeur peuvent être identique mais pas le champ param qui doit être unique.
 
Avant de faire mon traitement je veux donc analyser mon fichier pour contrôler que je n'ai pas deux fois la même valeur dans le champ param.
Si c'est le cas il faut que j'arrêt la.
 
Par exemple si mon fichier est le suivant :
 
cmd1 param1 valeur1
cmd2 param2 valeur2
cmd3 param1 valeur3
cmd1 param3 valeur4
cmd2 param2 valeur5
cmd4 param4 valeur6
cmd5 param2 valeur7
 
Je dois sortir en précisant que le param1 a été trouvé 2 fois et que le param2 à été trouvé 3 fois.
 
Voila ce que j'ai essayé de faire :
 

Code :
  1. open(F, 'cmd.txt') || die "Problème à l\'ouverture : $!";
  2. my $num_cmd = 0;
  3. while(<F> )
  4. {
  5. push @cmd,$_;
  6. $num_cmd ++;
  7. }
  8. close F || die "Problème à la fermeture : $!";
  9. ########################################################
  10. # compte le nombre de fois ou le paramètre est présent #
  11. ########################################################
  12. my %myhash;
  13. my @parsed;
  14. my $arret=0;
  15. my $h=0;
  16. foreach (@cmd)
  17. {
  18. @parsed = split /\s*\ \s*/, $_;
  19. $myhash{$parsed[1]}++;
  20. }
  21. foreach (sort {$myhash{$b} <=> $myhash{$a}} (keys(%myhash)))
  22. {
  23. m/([^.]+)\.(.*)/;
  24. if ($myhash{$_} != 1)
  25. {
  26.  print LOG "Une action sur $2 est present $myhash{$_} fois\n";
  27.  $arret=1;
  28. }
  29. }
  30. ####################################################
  31. # arrêt si le paramètre est présent plusieurs fois #
  32. ####################################################
  33. if ($arret == 1)
  34. {
  35. print LOG "ARRET de l'update\n";
  36. print "Probleme UPDATE non fait, voir la log\n";
  37. exit;
  38. }


 
Ca fonctionne sauf que j'ai le message suivant :
Use of uninitialized value in concatenation (.) or string at E:\Outils\update\maj.pl line 114.
Use of uninitialized value in concatenation (.) or string at E:\Outils\update\maj.pl line 114.
Probleme UPDATE non fait, voir la log
 
Et dans mon fichier de LOG :
 
Une action sur  est present 2 fois
Une action sur  est present 3 fois
ARRET de l'update
 
Merci de votre aide :jap:
 
 
 
 
 

mood
Publicité
Posté le 02-02-2017 à 17:02:22  profilanswer
 

n°2295717
gilou
Modérateur
Modzilla
Posté le 02-02-2017 à 23:58:28  profilanswer
 

Donc un truc dans ce gout ci:

Code :
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. my %params;
  7.  
  8. open(my $fh, '<', 'cmd.txt');
  9. while (<$fh> ) {
  10.    $params{$1}++ if (/^\s*(?:\S+)\s+(\S+)\s+(?:\S+)\s*$/);
  11. }
  12. close($fh);
  13.  
  14. # classement par nb de fois
  15. foreach (sort {$params{$b} <=> $params{$a}} (keys(%params))) {
  16.    if ($params{$_} > 1) {
  17.     print "le $_ a ete trouve $params{$_} fois\n";
  18.    }
  19. }


Et pour classer par nom de param, il suffit de virer le {$params{$b} <=> $params{$a}} devant sort.
 
Et pour une version bien organisee permettant une sortie sans passer par un appel a exit:

Code :
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. my %params;
  7.  
  8. open(my $fh, '<', 'cmd.txt');
  9. while (<$fh> ) {
  10.    $params{$1}++ if (/^\s*(?:\S+)\s+(\S+)\s+(?:\S+)\s*$/);
  11. }
  12. close($fh);
  13.  
  14. foreach (keys(%params)) {
  15.    delete $params{$_} if ($params{$_} < 2);
  16. }
  17.  
  18. if (%params) {
  19.    # classement par nb de fois
  20.    foreach (sort {$params{$b} <=> $params{$a}} (keys(%params))){
  21.        print "le $_ a ete trouve $params{$_} fois\n";
  22.    }
  23.    # message de fin de traitement, en erreur
  24. }
  25. else {
  26.    # proceder au traitement
  27. }


 
A+,


Message édité par gilou le 03-02-2017 à 00:38:07

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2295741
web_olivie​r
R1 Powaaaaa
Posté le 03-02-2017 à 11:06:36  profilanswer
 

Bonjour,
 
Merci beaucoup Gilou :) ça fonctionne très bien.  :bounce:  
 
J'ai juste oublié de préciser une petite chose, mais elle est importante.
Il n'y a pas forcément de champ valeur et dans ce cas ça ne fonctionne plus.
 
J'essaie de comprendre ce que tu as fais, mais je ne trouve pas la solution si le champ valeur est absent.
 
 :jap:

n°2295778
gilou
Modérateur
Modzilla
Posté le 04-02-2017 à 11:27:06  profilanswer
 

Bonjour, s'il n'y a pas de champ valeur, ça simplifie les choses:
/^\s*\S+\s+(\S+)/
On ne parse plus que les deux champs obligatoires en début de ligne.
(bon, on pouvait déjà aussi faire comme ça avant, parser la ligne complète permettait juste de s'assurer qu'on ne parsait que les lignes a trois champs obligatoires).
 
A+,


Message édité par gilou le 04-02-2017 à 11:44:10

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2295825
web_olivie​r
R1 Powaaaaa
Posté le 06-02-2017 à 10:37:54  profilanswer
 

Bonjour,
 
Encore une fois un grand merci Gilou ça fonctionne parfaitement.
Si je peux me permettre peux tu m'expliquer la regex /^\s*\S+\s+(\S+)/ ?
 
:jap:

n°2295840
h3bus
Troll Inside
Posté le 06-02-2017 à 13:27:23  profilanswer
 

Tu peux utiliser ce site pour tester/expliquer des regexp, c'est très pratique.
https://regex101.com/


---------------
sheep++
n°2295844
web_olivie​r
R1 Powaaaaa
Posté le 06-02-2017 à 13:40:17  profilanswer
 

:jap:

n°2295888
gilou
Modérateur
Modzilla
Posté le 06-02-2017 à 17:34:46  profilanswer
 

/
^      Debut de ligne suivi de  
\s*    Blancs (SPACE ou TAB) optionnels en debut de ligne suivis de  
\S+    un ou plusieurs caracteres differents de space et TAB  (\S c'est le contraire de \s)
\s+    un ou plusieurs blancs  
(\S+) un ou plusieurs caracteres differents de space et TAB copies dans groupe (donc $1)
/  
Comme on est en mode greedy (on matche le plus grand nombre de caractères possibles), on sait que (\S+) va capturer tous les caractères jusqu’à ce qu'il rencontre un SPACE, TAB ou la fin de la ligne.
 
A+,


Message édité par gilou le 06-02-2017 à 17:40:06

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2295957
web_olivie​r
R1 Powaaaaa
Posté le 07-02-2017 à 15:40:18  profilanswer
 

Milles Merci.
 
:jap:
 
Maintenant je dois faire la même chose en java :(
J'ouvre un autre Topic :bounce:


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Perl

  [Perl] Arrêt traitement si doublons dans champ d'un fichier

 

Sujets relatifs
problème sur fichier launch.batEliminer les doublons (résolu)
transformer un fichier texte en XMLrecherche d'un mot dans un fichier
bon fichiervba-copier des colonnes d'un fichier xls vers un autre fichier xls
Splitter (découper) un fichier CSVSupprimez le fichier image uploded utilisant le code d'ajax
Choix de configurations a l'ouverture d'un fichier ExcelLire ou Télécharger un fichier sur un FTP
Plus de sujets relatifs à : [Perl] Arrêt traitement si doublons dans champ d'un fichier


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR