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

  FORUM HardWare.fr
  Programmation
  Perl

  Remplacer caractères héxa : PERL

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Remplacer caractères héxa : PERL

n°2012792
perly
Posté le 29-07-2010 à 10:33:38  profilanswer
 

Bonjour,
 
Je veux remplacer plusieurs caractères hexa (plus de 2) par un ou plusieurs autres caractères héxa avec perl.
 
Exemple :
remplacer 0D0A46 par 45
 
Apparement avec \x sous perl ça marche que pour un seul caractère hexa!
 
Avez-vous des solutions?
 
 
Merci

mood
Publicité
Posté le 29-07-2010 à 10:33:38  profilanswer
 

n°2012895
gilou
Modérateur
Modzilla
Posté le 29-07-2010 à 13:55:01  profilanswer
 

$machaine =~ s/\x0D\x0A\x46/\x45/g;
A+,

Message cité 1 fois
Message édité par gilou le 29-07-2010 à 13:55:16

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2013020
perly
Posté le 29-07-2010 à 20:32:01  profilanswer
 

gilou a écrit :

$machaine =~ s/\x0D\x0A\x46/\x45/g;
A+,


merci mais ça ne marche pas.
 
Pour tester j'ai créer un programme en vert ça marche en rouge ça marche pas.  
Donc un hexa ok plus de 2 pas ok

Code :
  1. #!/usr/bin/perl -w
  2. use strict;
  3. $| = 1;
  4. my ($f);
  5. print "Chemin fichier: " and chomp($f = <STDIN> );
  6. open FIC, $f or die "$f : $!\n";
  7. open FILE, '>tmp.txt' or die "tmp.txt : $!\n";
  8. my $i = 1;
  9. while (<FIC> ) {   
  10.       s/\x01/\x45/g;
  11.       s/\x01\x0D\x46/\x45/g;
  12.       print FILE ; 
  13.    $i++;
  14. }
  15. close FIC and close FILE;
  16. unlink $f;
  17. rename "tmp.txt", $f;
  18. print "ok";


Rmq : J'utilise PsPad pour écrire des hexa. D'abord j'écris n'importe quoi dans mon fichier puis je remplace avec PsPadHEX certains caractères.


Message édité par perly le 29-07-2010 à 20:33:23
n°2013023
gilou
Modérateur
Modzilla
Posté le 29-07-2010 à 21:08:32  profilanswer
 

:hello:
Bien sur que la, ca va pas marcher, puisque tu ouvres ton fichier en mode ligne à ligne, et que dans ton pattern recherché, il y a un caractère de fin de ligne (\x0A)  :sarcastic: (tes hexa substitués, c'est "\r\nF" ).
Il n'a été dit nulle part dans ta présentation initiale du problème, que ce que tu voulais substituer provenait d'une boucle de lecture de fichier, et vu qu'il y avait un \n au milieu de ton pattern cherché, il semblait même illogique que ce soit le cas.

 

Tu as deux possibilités:
Soit tes fichiers sont petit en mémoire, et tu lis tout ton fichier dans une variable texte pour lui appliquer la substitution:

Code :
  1. {
  2.    local( $/ ) ;
  3.    open( my $fh, $file ) or die "cannot open file $f\n"
  4.    binmode $fh; #sous dos windows, \r\n est transformé en \n automatiquement si on en fait pas ça
  5.    $text = <$fh>
  6.    $text =~ s/\x0D\x0A\x46/\x45/g;
  7.    # ? print $text qque part
  8. }
 

Soit il faut avancer ligne a ligne et éclater ton pattern recherché en deux, celui avant  la fin de ligne /\r\n$/ et celui après /^F/
et faire de une boucle qui teste lorsqu'une ligne a le bon pattern, si la ligne suivante l'a aussi on fait la substitution.
C'est plus coton (il faut mémoriser la ligne précédente et ne pas l'envoyer tout de suite en sortie) mais pas bien dur.
Ne pas oublier la aussi le binmode après ouverture du fichier, sinon, on ne verra jamais passer un \x0D\x0A.

 

A+,


Message édité par gilou le 29-07-2010 à 21:40:29

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2013561
perly
Posté le 02-08-2010 à 12:22:38  profilanswer
 

Merci pour ta réponse.  
 
J'ai trouvé :sol: , c'était très simple en fait. Dans perl il suffit de rajouter des crochets entre \r\n [\x0D\x0A]
 

Code :
  1. #!/usr/bin/perl -w
  2. use strict;
  3. $| = 1;
  4. my ($f);
  5. print "Chemin fichier: " and chomp($f = <STDIN> );
  6. open FIC, $f or die "$f : $!\n";
  7. open FILE, '>tmp.txt' or die "tmp.txt : $!\n";
  8. while (<FIC> ) { 
  9.       s/\x01[\x0D\x0A]/\x45/g;
  10.        print FILE ;
  11. }
  12. close FIC and close FILE;
  13. unlink $f;
  14. rename "tmp.txt", $f;


 
 

n°2013579
gilou
Modérateur
Modzilla
Posté le 02-08-2010 à 13:50:47  profilanswer
 

Citation :

il suffit de rajouter des crochets


Euh non, c'est juste totalement faux, ça.
C'est pas la même expression régulière:
\x01[\x0D\x0A]  c'est la même chose que \x01(\x0D|\x0A) c'est à dire \x01(\r|\n) et c'est donc pas du tout pareil que \x01\r\n
L'écriture entre [] n'a d'intérêt que si on fait un range [\x0A-\x0D] ou une négation [^\x0A]

 

Pourquoi le code que tu as écrit a des chances de marcher (sous dos windows)
1) manifestement, tu n'ouvres pas le fichier en mode binaire, donc les \r\n sont remappés par perl automatiquement en \n
donc tu remplacerait ton expression x01[\x0D\x0A] par x01\x0A que ça marcherait pareil
Donc effectivement, après ce remappage automatique, si on veut chercher ce qui est comme \x01\r\n dans le fichier, il va falloir chercher \x01\n
Et comme maintenant, avec ton \x01[\x0D\x0A] tu ne cherches plus comme avant \x01\x0D\x0A mais \x01(\x0D|\x0A) ce qui équivaut à (\x01\x0D|\x01\x0A) la seconde alternative \x01\x0A ie \x01\n va matcher ton \x01\r\n après le remappage de perl en \x01\n
Si tu avais lu ma réponse précédente et ouvert le fichier en mode binaire, il y aurait pas de remappage, et chercher \x01\x0D\x0A marcherait très bien.
2) ce coup ci, en mode lecture ligne à ligne, tu ne cherches plus une expression régulière avec un \n au milieu (ce qui ne pouvait pas être matché), mais avec un \n à la fin
Donc effectivement, ce coup ci, ça va pouvoir être matché, contrairement à ce que tu faisais avant (ou tu voulais un \x46 en début de ligne suivante)

 

Donc si ça marche maintenant, c'est pas du tout pour les raisons que tu donnes.

 

A+,


Message édité par gilou le 02-08-2010 à 13:52:39

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2013693
perly
Posté le 02-08-2010 à 17:36:17  profilanswer
 

Autant pour moi!
Je te remercie pour tes explications d'expert.
 
Donc si j'ai un \n au milieu de l'expression régulière je procède comment?
 
Par exemple si j'ai FR\r\nANG que je veux remplacer par FR\r\nENG
 
je procède comme cela car ça n'a pas l'air de marcher :  
 

Code :
  1. ...
  2. open FIC, $f or die "$f : $!\n";
  3. binmode $f;
  4. ...
  5. while (<FIC> ) { 
  6.        s/FR\x0D\x0AANG/FR\x0D\x0AENG/g;
  7.     $i++;
  8. }
  9. ...


 
Merci.
A+

n°2013717
gilou
Modérateur
Modzilla
Posté le 02-08-2010 à 19:53:08  profilanswer
 

Comme je te l'ai dit, tu peux pas si tu as ça dans une lecture ligne a ligne, car ton while (<FIC> ) va d'abord chopper le FR\r\n puis le ANG puisque ça lit ligne à ligne.

 

Comme je te l'avais indiqué, il y a deux méthodes:
Tout lire dans une seule grande ligne (pas possible si le fichier est trop gros).
On fait

 
Code :
  1. {
  2.    local( $/ ) ;
  3.    open( my $fh, $file ) or die "cannot open file $f\n"
  4.    binmode $fh; #sous dos windows, \r\n est transformé en \n automatiquement si on en fait pas ça
  5.    $text = <$fh>; # lit tout d'un coup
  6.    $text =~ s/FR\r\nANG/FR\r\nENG/g;
  7.    # ? print $text qque part
  8. }


1) on met dans un bloc {} sinon, ça risque de foutre le bordel ailleurs
2) on fait local( $/ ) ;  pour lire sans s'arrêter a chaque \r\n (windows) ou \n (unix) cette redéfinition étant limitée au bloc
3) on lit tout en un seul coup dans une variable
4) on fait le remplacement sur le contenu de la variable
5) on sauve la variable modifiée dans le fichier de sortie.

 

L'autre méthode, c'est de procéder en deux temps; On cherche /FR\r\n$/ et quand on a trouvé ça, on le mémorise pour voir si la ligne suivante commence par /^ENG/ et si oui, on fait le remplacement:

 
Code :
  1. my $found = 0;
  2. my $ligprec = "";
  3. while ( <FH> ) {
  4.    if ($found) {
  5.        if (/^ANG/) {
  6.            # On a matché le pattern cherché
  7.            # on fait ce qu'on veut sur $ligprec et $_ en fonction de ses besoins
  8.            ############################################################################
  9.            # ici, c'est juste la deuxième ligne qu'on modifie
  10.            # on ne fait rien a la ligne sauvegardée, donc on va l'imprimer telle quelle
  11.            print $ligprec;
  12.            # On fait la modif
  13.            s/^ANG/ENG/o;
  14.            ############################################################################
  15.        }
  16.        else {
  17.            # pas trouvé, donc on imprime la ligne sauvegardée
  18.            print $ligprec;
  19.        }
  20.        #reset des variables de sauvegarde
  21.        $found = 0;
  22.        $ligprec = "";
  23.    }
  24.    if (/FR\r\n$/) {
  25.        $found = 1;
  26.        # On sauvegarde la ligne
  27.        $ligprec = $_;
  28.        #on boucle sans l'imprimer
  29.        next;
  30.    }
  31.    else {
  32.        print;
  33.    }
  34. }
  35. if ($found) {
  36.    # la derniere ligne du fichier se terminait FR\r\n et a été sauvegardée
  37.    # on imprime cette ligne sauvegardée
  38.    print $ligprec;
  39. }


Note que j'ai fait du code pédagogique, mais perso, ce serait my $ligprec; en ligne 2 et undef $ligprec; en ligne 22 que j'écrirais dans du vrai code.
A+,


Message édité par gilou le 02-08-2010 à 20:01:37

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

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

  Remplacer caractères héxa : PERL

 

Sujets relatifs
[Divers] Demander au modem de renvoyer une chaine de caracteresFormatage sequences en perl
caractères ^M lors de copies de fichiers[Résolu][Batch] Comparaison chaines de caractères
comparaison caractèresAffichage de caractères polonais depuis un xml
perl Net::Telnet : comment choisir l'interface ?probleme caracteres UNIX-WINDOWS en php
[DELPHI] Verifier les caractères d'un string ![perl] le meilleur moyen pour ramener une valeur ?
Plus de sujets relatifs à : Remplacer caractères héxa : PERL


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