Test chaine dans un fichier

Test chaine dans un fichier - Perl - Programmation

Marsh Posté le 17-09-2014 à 15:42:51    

Bonjour,
 
J'aimerai tester si des valeurs sont présentes dans un fichier texte ou non.
J'ai commencé le code suivant mais il ne fonctionne que s'il y a qu'une valeur dans mon fichier texte.
 
Ex du fichier txt :
 
test1
test2
 
Voici mon code :

Code :
  1. open(FILE,"$file" ) || die ("Erreur d'ouverture du fichier" ) ;
  2. while (<FILE> ) {
  3.   $_ =~ s/\n//g;
  4.   if ($_ eq $ligne) {
  5.       print "Fichier deja present\n";
  6.   } else {
  7.       print "Fichier $ligne non present\n";
  8.   }
  9. }


 
Admettons que la variable $ligne soit égale à test1, le code me renvoi les deux tests, c'est à dire :
Fichier test1 non present
Fichier deja present
 
Est ce que quelqu'un pourrait m'aider à comprendre mon erreur svp ?
Merci

Reply

Marsh Posté le 17-09-2014 à 15:42:51   

Reply

Marsh Posté le 17-09-2014 à 18:41:02    

Bonsoir,
C'est normal, vu que ton while execute le test ligne par ligne.
Pour la ligne égale a test1, le test est OK et ça imprime  "Fichier deja present", et pour la ligne a test2, le test est  pas vérifié, et ça imprime "Fichier $ligne non present"
Une solution:
Créer une variable a valeur 0 et la passer a 1 (et sortir de la boucle while) si le test est verifié (cf last en perl).
Et une fois la boucle terminée, imprimer selon la valeur de cette variable (elle est toujours a 0 si aucune ligne n'était égale a test1)
Autre remarque, quand on fait un open, il est bon de faire aussi un close.
 
A+,


Message édité par gilou le 17-09-2014 à 18:45:55

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 17-09-2014 à 18:55:19    

Merci Gilou pour ta réponse.
Oui bien sur j'ai fais un close, j'ai simplement pas affiché tout le code.
 
Par contre est ce que ta solution fonctionne pour une multitude de fichier ?
Car j'ai mis l'exemple de deux fichiers mais dans la réalité dans ce fameux fichier texte, il y aura des centaines de fichiers !
 
Autre chose aussi ! Le programme doit vérifier la présence également de plusieurs fichiers dans le fichier texte.

Reply

Marsh Posté le 17-09-2014 à 23:58:33    

> Le programme doit vérifier la présence également de plusieurs fichiers dans le fichier texte.
 
Dans ce cas la, au lieu d'une variable, tu crées un hash
my %hash
et si tu as un test validé  
if ($_ eq "test18" )
par exemple
tu fais
$hash{"test18"}++;
et tu ne sors alors pas du while avec un last (c'était bon que si on recherchait une seule valeur, cette optimisation)
une fois le while terminé les clés du hash seront les valeurs détectées dans le fichier par les tests.
 
A+,


Message édité par gilou le 18-09-2014 à 00:00:22

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 18-09-2014 à 13:04:29    

Bonjour Gilou,
J'ai regarder ce que c'était le hash donc j'ai bien compris que c'était associé à un tableau !
Par contre étant vraiment novice, j'ai du mal à mettre ça en place et à m'en sortir.
 
Pourrais-tu me guider un peu plus stp ?
En attendant merci de ton aide.

Reply

Marsh Posté le 18-09-2014 à 13:53:13    

Ben un truc comme ceci:

Code :
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5. use autodie;
  6.  
  7. my $filename = "testkw.txt";
  8. my @keywords = qw(toto tata tutu);
  9. my %kwfound;
  10.  
  11. open my $fh, "<", $filename;
  12. while (<$fh> ) {
  13.  s/\n$//o;
  14.  foreach my $kw (@keywords) {
  15.    if ($_ eq $kw) {
  16.      ++$kwfound{$kw};
  17.    }
  18.  }
  19. }
  20. close $fh;
  21.  
  22. foreach my $kw (keys %kwfound) {
  23.  print "keyword $kw found in $filename\n";
  24. }
 

A+,


Message édité par gilou le 18-09-2014 à 13:54:32

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 18-09-2014 à 14:38:37    

coolkis a écrit :

Bonjour Gilou,
J'ai regarder ce que c'était le hash donc j'ai bien compris que c'était associé à un tableau !


En perl, les types composites sont la liste et le hash.
Un hash c'est une variable associée a une sorte de tableau, mais dans lequel les éléments, au lieu d'être indexés par des entiers comme dans une liste, sont indexés par des valeurs uniques, les clés.
 
my %kwfound;  # je déclare un hash, kwfound
++$kwfound{$kw}; # perl cherche si le hash kwfound a une entrée pour la clé de valeur $kw. Si oui, il incrémente la valeur de 1 (le ++), sinon, il crée dans kwfound une nouvelle entrée pour la cké de valeur $kw, et comme on veut faire une opération numérique dessus, il l'initialise a 0, puis il l'incrémente (le ++) et la valeur sera alors 1.
 
A+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 18-09-2014 à 16:01:10    

Ok super ! Merci bcp encore, j'ai bien compris le fonctionnement.
Par contre si le fichier recherché n'est pas dans le fichier texte, je voudrais l'ajouter !
 
Est ce que cela se passe dans le "foreach" ?

Reply

Marsh Posté le 18-09-2014 à 18:16:41    

Non.
Il faudra rouvrir le fichier texte en écriture, en mode ajout à la fin, et écrire la ligne manquante dedans.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-09-2014 à 14:10:13    

Oui je suis bien d'accord.
 
Je comptais faire un truc du genre :
 
foreach my $kw (@keywords) {
    if ($_ eq $kw) {
      ++$kwfound{$kw};
    } else {
         ajout du fichier...
    }
}
 
Ce n'est pas la bonne méthode ça ?

Reply

Marsh Posté le 19-09-2014 à 14:10:13   

Reply

Marsh Posté le 19-09-2014 à 15:02:40    

Non, c'est pas à ce niveau la, puisque le test foreach my $kw (@keywords) se fait ligne a ligne.
 
Par contre, quand on aura fini de lire le fichier, plutôt que  
 
    foreach my $kw (keys %kwfound) {
     print "keyword $kw found in $filename\n";
    }
 
on peut faire
 
foreach my $kw (@keywords) {
    # si on ne l'a pas trouvé dans le fichier texte
    if (!defined($kwfound{$kw})) {
         ajout du fichier...
    }
}  
 
et pour que ça marche, il faut  
1) avoir ouvert le fichier en lecture/écriture
2) le fermer après tout ça et non plus avant
Comme après le remplissage de %kwfound on a lu tout le fichier, on est en fin de fichier, et donc on peut ajouter du texte sans craindre d'écrire par dessus du contenu féjà présent.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-09-2014 à 16:41:06    

Une fois de plus, merci beaucoup pour ton aide Gilou.
 
Voici ce que ça donne :
 
foreach my $kw (@keywords) {
  if (!defined($kwfound{$kw})) {
    open(FILE, ">>$filename" ) || die ("Erreur d'ouverture du fichier" );
    print FILE "${kw}\n";
  } else {
      print "Fichier $kw deja present $filename\n";
  }
}
close (FILE);

Reply

Marsh Posté le 19-09-2014 à 17:03:01    

> open(FILE, ">>$filename" )  
Surtout pas!
Tu vas pas ouvrir le fichier une fois par mot manquant et jamais le refermer...
 
Le plus simple c'est d'ouvrir en read-write le fichier au départ
open my $fh, "+<", $filename;
 
et de faire à la fin
 
foreach my $kw (@keywords) {
  if (!defined($kwfound{$kw})) {
    print $fh "${kw}\n";
  } else {
      print "Fichier $kw deja present $filename\n";
  }
}
close $fh;
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-09-2014 à 18:19:52    

Ok ! En fait j'avais déjà fait un << close $fh; >> avant la boucle, c'est pour cela que j'ai refais un open derrière. Mais effectivement c'est plus propre comme cela ;-)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed