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

  FORUM HardWare.fr
  Programmation
  Perl

  [PERL] Remplacement récursif

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[PERL] Remplacement récursif

n°2033698
bob_64
Posté le 02-11-2010 à 21:46:38  profilanswer
 

Bonjour,
 
Je suis débutant en PERL et je dois faire un script qui doit remplacer toutes les occurences du nombre 34 par le nombre 99 dans tous les fichiers c contenus dans le répertoire courant mais aussi dans tous les autres sous-répertoires (il y en a beaucoup, ce sera fastidieux de le faire à la main). Pour cela j'ai essayé 2 méthodes mais qui n'ont pas abouti :
 
la 1ère :
j'ai créé le script suivant :
 
#!/bin/perl
 
@ARGV= glob "*.c";
 
while (my $ligne = <> ) {
 
$ligne =~ s/34/99/;
 
print $ligne;
}
 
que j'appelle de la manière suivante :
find . -name "*.c" -exec perl -i script.pl {} \;
J'utilise le find pour appliquer le script à tous les fichiers c trouvés mais l'exécution de ce script ne modifie que les fichiers du répertoire courant et pas ceux des sous-répertoires.
 
la 2ème :
j'ai créé le script suivant :
#!/bin/perl
 
use File::Find;
 
sub process_file {
while (my $ligne = <> ) {
$ligne =~ s/34/99/;
print $ligne;
}
}
 
find(\&process_file, $ARGV[0]);
 
que j'appelle de la manière suivante :
perl -i script_2.pl *.c
 
mais la encore même résultat que précédemment, les fichiers des sous-répertoire ne sont pas modifiés.
 
Quelqu'un aurait-il une idée?
 
 
Bob_64

mood
Publicité
Posté le 02-11-2010 à 21:46:38  profilanswer
 

n°2033707
olivthill
Posté le 02-11-2010 à 23:17:26  profilanswer
 

C'est bizarre, il y a eu presque la même question, très récemment, voir  
http://forum.hardware.fr/hfr/Progr [...] 1277_1.htm
 
Peut-être que le script n'est pas trouvé, et qu'il faudrait lui préciser son chemin avant son nom.
Sinon, on peut aussi ajouter un -type f qui ne fait pas de mal et qui précise que seuls les fichiers doivent être considérés.


Message édité par olivthill le 02-11-2010 à 23:22:54
n°2033741
gilou
Modérateur
Modzilla
Posté le 03-11-2010 à 10:34:13  profilanswer
 

perl -i script_2.pl *.c  
1) ton shell va transformer le *.c en une liste des noms de fichiers .c du répertoire courant, liste passée en argument au script
2) le script perl execute find(\&process_file, $ARGV[0]);  
 $ARGV[0] est le premier des noms de la liste des noms de fichiers .c du répertoire courant
C'est un nom de fichier, pas un nom de répertoire, ce que le find du script attend, donc il est pas surprenant qu'il aille pas récursivement dans les sous répertoires.
Tu as même de la chance que ça marche pour le répertoire courant.
 
Dans ton script perl, il faut
- passer le nom du répertoire comme argument au script
- s'il y en a pas de passé, prendre celui du repertoire courant ( use Cwd;   my $dir = getcwd;)
- verifier que le fichier est bien un fichier et que son nom est en *.c, sinon ne rien faire, au début de process_file
  faire le changement voulu dans le fichier si c'est OK
 
Note sur ton expression régulière: si on veut remplacer les 34 par 99, il faut peut être faire attention a ne pas remplacer 345 par 995 par exemple...
 
A+,


Message édité par gilou le 03-11-2010 à 10:37:23

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2033784
gilou
Modérateur
Modzilla
Posté le 03-11-2010 à 13:16:18  profilanswer
 

Un exemple de solution possible

Code :
  1. #!/usr/local/bin/perl -w
  2. use strict;
  3. use warnings;
  4.  
  5. use File::Find;
  6. use Cwd;
  7.  
  8. # si pas d'argument, on prend le répertoire courant
  9. $ARGV[0] = getcwd unless defined ($ARGV[0]);
  10. # On processe la liste des arguments
  11. foreach (@ARGV) {
  12.    #on applique le find si c'est un répertoire seulement
  13.    find(\&process_file, $_) if (-d);
  14. }
  15.  
  16. sub process_file {
  17.    #on ne traite que les fichiers c
  18.    return unless (-f && /.+\.c$/o);
  19.    # on ouvre et on lit le fichier dans un array
  20.    open(my $fh, '<', $_) or return;
  21.    my @lines = <$fh>;
  22.    close($fh);
  23.    # on fait la substitution dans l'array
  24.    map {s/(^|\D)34(?=\D|$)/${1}99/go} @lines;
  25.    # on ouvre et réécrit le fichier
  26.    open($fh, '>', $_) or return;
  27.    print $fh @lines;
  28.    close($fh);
  29. }


Une variante, plus courte, pas nécessairement plus efficace

Code :
  1. #!/usr/local/bin/perl -w
  2. use strict;
  3. use warnings;
  4.  
  5. use File::Find;
  6. use Cwd;
  7. use Tie::File;
  8.  
  9. # si pas d'argument, on prend le répertoire courant
  10. $ARGV[0] = getcwd unless defined ($ARGV[0]);
  11. # On processe la liste des arguments
  12. foreach (@ARGV) {
  13.    #on applique le find si c'est un répertoire seulement
  14.    find(\&process_file, $_) if (-d);
  15. }
  16.  
  17. sub process_file {
  18.    #on ne traite que les fichiers c
  19.    return unless (-f && /.+\.txt$/o);
  20.    # on associe le fichier à un array
  21.    tie my @lines, 'Tie::File', $_ or return;
  22.    # on effectue la substitution
  23.    map {s/(^|\D)34(?=\D|$)/${1}99/go} @lines;
  24.    untie @lines;
  25. }


A+,


Message édité par gilou le 03-11-2010 à 13:51:38

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2035464
bob_64
Posté le 11-11-2010 à 19:37:33  profilanswer
 

Merci beaucoup pour la réponse et les explications, cela marche à merveille :)
 
Bob_64


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

  [PERL] Remplacement récursif

 

Sujets relatifs
Aide sur l'execution d'un code en perlMacro remplacement de point par virgules
[Perl] - Programmation objet et debugger[RESOLU] Remplacement d'une chaine de caractères dans un fichier html
[PERL?] interface texte avec gestion des touches directionnellesRemplacer caractères héxa : PERL
Formatage sequences en perlperl Net::Telnet : comment choisir l'interface ?
[perl] le meilleur moyen pour ramener une valeur ?Remplacement d'un motif dans une chaine de caractères
Plus de sujets relatifs à : [PERL] Remplacement récursif


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