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

  FORUM HardWare.fr
  Programmation
  Perl

  [Perl] Remplacer plusieurs lignes par le résultat d'un appel externe

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Perl] Remplacer plusieurs lignes par le résultat d'un appel externe

n°2307213
rotoutou
Across member
Posté le 02-11-2017 à 17:29:34  profilanswer
 

Plop tous  :hello:  
 
Je crée ce topic sur [Perl] car je pense que je vais finir par arriver ici.
 
En fait je rencontre un problème, et je n'arrive pas à conceptualiser la résolution en sed ou awk, et en cherchant sur le net pas mal de résultats renvoie sur l'utilisation de Perl
 
Donc je vous présente mon souci, pour avis & conseil :
 
J'ai un fichier contenant un dump de ce qui passe à travers un RP :
 

2017-10-24-14:22:40.404+00:00I----- thread(222)
----------------------------------------
Thread 140293241104128; fd 32; local 111.111.111.111:443; remote 222.222.222.222:39952
Receiving 797 bytes
0x0000   4745 5420 2f6d 6761 2f73 7073 2f61 7574        GET./mga/sps/aut
0x0010   6820 4854 5450 2f31 2e31 0d0a 486f 7374        h.HTTP/1.1..Host
...
0x02d0   6374 696f 6e2d 4944 3a20 3238 3434 3431        ction-ID:.284441
0x02e0   3234 3439 0d0a 436f 6e6e 6563 7469 6f6e        2449..Connection
0x02f0   3a20 4b65 6570 2d41 6c69 7665 0d0a 4361        :.Keep-Alive..Ca
0x0300   6368 652d 436f 6e74 726f 6c3a 206e 6f2d        che-Control:.no-
0x0310   7472 616e 7366 6f72 6d0d 0a0d 0a               transform....    
 
----------------------------------------
 
2017-10-24-14:22:40.405+00:00I----- thread(222)
----------------------------------------
Thread 140293241104128; fd 32; local 111.111.111.111:443; remote 222.222.222.222:39952
Sending 6621 bytes
0x0000   4854 5450 2f31 2e31 2032 3030 204f 4b0d        HTTP/1.1.200.OK.
0x0010   0a63 6f6e 7465 6e74 2d6c 656e 6774 683a        .content-length:
0x0020   2036 3332 390d 0a63 6f6e 7465 6e74 2d74        .6329..content-t
0x0030   7970 653a 2074 6578 742f 6874 6d6c 0d0a        ype:.text/html..
0x0040   6461 7465 3a20 5475 652c 2032 3420 4f63        date:.Tue,.24.Oc
...
0x19a0   7574 696c 6973 6174 696f 6e3c 2f61 3e0a        utilisation</a>.
0x19b0   0909 0909 3c2f 6c69 3e0a 0909 093c 2f75        ....</li>....</u
0x19c0   6c3e 0a09 093c 2f64 6976 3e0a 093c 2f62        l>...</div>..</b
0x19d0   6f64 793e 0a3c 2f68 746d 6c3e 0a               ody>.</html>.    


Y a des lignes pour décrire le contexte (appelant, nb bytes transmis, etc.), et un hexdump de ce qui passe.
 
J'aimerais isoler les lignes avec l'hexa, les envoyer dans un appel à par exemple `xxd -r -p` pour récupérer le résultat et substituer tout le contenu par le résultat de l'appel
 
Pour obtenir :

2017-10-24-14:22:40.404+00:00I----- thread(222)
----------------------------------------
Thread 140293241104128; fd 32; local 111.111.111.111:443; remote 222.222.222.222:39952
Receiving 797 bytes
GET /mga/sps/auth HTTP/1.1
Host...
...
...ction-ID: 2844412449
Connection: Keep-Alive
Cache-Control: no-transform    
 
----------------------------------------
 
2017-10-24-14:22:40.405+00:00I----- thread(222)
----------------------------------------
Thread 140293241104128; fd 32; local 111.111.111.111:443; remote 222.222.222.222:39952
Sending 6621 bytes
HTTP/1.1 200 OK
content-length: 6329
content-type: text/html
date: Tue, 24.Oc...
...
     ...utilisation</a>
    </li>
   </ul>
  </div>
 </body>
</html>


Avec la regex 0x[a-f0-9]{4}\s{3}(.{39})\s{8}.*
j'arrive à isoler - pour une ligne - l'hexa
 
avec sed je pensais utiliser le hold buffer pour stocker le groupe \1 des lignes matchées, et dans l'event "fin" (ligne vide suivant les lignes hexa) pousser ça dans le xxd et replace mon buffer avec le résultat de l'appel
(et les lignes non matchées sont printées par défaut, pour avoir les lignes non hexa dans le fichier résultat)
 
mais apparemment mon cerveau est trop petit pour faire ça :o (ou trop nul en sed)
 
ça pourrait se simplifier avec Perl ?
 
genre lire le fichier ligne par ligne, appliquer la regexp, si found alors je crée un buffer et pousse le groupe matché, et si je sors de mon match je termine mon buffer, j'appelle xxd -r sur le contenu et printe la valeur du résultat de l'appel.
si pas de match je printe la ligne
 
(le fichier à parser fait dans les 10Mo)
 
Je prends tous les bons conseils en regex, sed, awk, etc. :)


---------------
Reckless inferior depraved repentant ruinous foul-mouthed revered master Rotoutou the great.
mood
Publicité
Posté le 02-11-2017 à 17:29:34  profilanswer
 

n°2307216
rat de com​bat
attention rongeur méchant!
Posté le 02-11-2017 à 17:40:32  profilanswer
 

Pourquoi passer par xxd si tu as le texte directement à côté du hexa déjà? Si je vois bien ce que tu veux c'est exactement ce texte, avec les caractères non-imprimables remplacés par des points. edit: En fait non :o, attends, je vais adapter mon code, je reviens...

 

Sinon bien sûr ça peut se faire en Perl, attends...

 


Message édité par rat de combat le 02-11-2017 à 17:56:00
n°2307220
rotoutou
Across member
Posté le 02-11-2017 à 18:02:30  profilanswer
 

:p c’était mon premier essai, matcher le texte à coté (avec \n à la fin pour avoir directement le matching group sans le retour à la ligne), et remplacer directement dans notepad++ par \1
 
mais c'est pas terrible, et notepad++ perd les pédales assez rapidement.
 
Là j'ai commencé le truc en Perl, mais je coince sur la construction du buffer pour stocker les lignes hexa : est-ce qu'il faut prendre un buffer en mémoire ou un fichier temporaire ...


---------------
Reckless inferior depraved repentant ruinous foul-mouthed revered master Rotoutou the great.
n°2307221
rat de com​bat
attention rongeur méchant!
Posté le 02-11-2017 à 18:07:03  profilanswer
 

Deuxième tentative de ma part, en espérant que j'ai bien compris cette fois. :o

 
Code :
  1. use strict;
  2. use warnings FATAL=>'all';
  3. use autodie;
  4.  
  5. open my $input, '<', 'input';
  6.  
  7. my $buffer="";
  8.  
  9. while(<$input> )
  10. {
  11.    if(/^0x[[:xdigit:]]{4}\s+((?:[[:xdigit:]]{2,4}\s+)+)/)
  12.    {
  13.        my $hex=$1;
  14.        $hex=~s/\s+//g;
  15.        $buffer.=join('', map( { chr(hex($_)) } unpack('(A2)*', $hex)));
  16.        $buffer=~s/\r\n/\n/g; #corriger les retours à la ligne
  17.    }
  18.    else
  19.    {
  20.        print $buffer if($buffer);
  21.        print $_;
  22.        $buffer="";
  23.    }
  24. }
  25. print $buffer if($buffer);
  26.  
  27. close $input;
 

Ca donne:

Code :
  1. 2017-10-24-14:22:40.404+00:00I----- thread(222)
  2. ----------------------------------------
  3. Thread 140293241104128; fd 32; local 111.111.111.111:443; remote 222.222.222.222:39952
  4. Receiving 797 bytes
  5. GET /mga/sps/auth HTTP/1.1
  6. Hostction-ID: 2844412449
  7. Connection: Keep-Alive
  8. Cache-Control: no-transform
  9. ----------------------------------------
  10. 2017-10-24-14:22:40.405+00:00I----- thread(222)
  11. ----------------------------------------
  12. Thread 140293241104128; fd 32; local 111.111.111.111:443; remote 222.222.222.222:39952
  13. Sending 6621 bytes
  14. HTTP/1.1 200 OK
  15. content-length: 6329
  16. content-type: text/html
  17. date: Tue, 24 Ocutilisation</a>
  18.                 </li>
  19.             </ul>
  20.         </div>
  21.     </body>
  22. </html>
 

edit: À toi de modifier pour écrire le résultat dans un fichier...
edit2: Inutile de faire un s/// si on ne réutilises pas $_, j'ai changé en m//.


Message édité par rat de combat le 02-11-2017 à 18:11:40
n°2307224
rotoutou
Across member
Posté le 02-11-2017 à 18:42:40  profilanswer
 

Merci beaucoup pour ton aide :hello:
 
j'ai rajouté de quoi écrire dans un fichier, ça marche nickel
 
Pour le $buffer.=join('', map( { chr(hex($_)) } unpack('(A2)*', $hex)));
J'imagine bien ce que ça fait, mais j'aurais pas trouvé ça :)
 
Je vais modifier tout ça pour dégager les truc "genre content-type: image/png" qui printent du caractère "bizarre", ça nettoiera un peu plus le fichier
 
encore merci ! :)


---------------
Reckless inferior depraved repentant ruinous foul-mouthed revered master Rotoutou the great.
n°2307225
rat de com​bat
attention rongeur méchant!
Posté le 02-11-2017 à 18:51:50  profilanswer
 

De rien. :)  

rotoutou a écrit :

Pour le $buffer.=join('', map( { chr(hex($_)) } unpack('(A2)*', $hex)));
J'imagine bien ce que ça fait, mais j'aurais pas trouvé ça :)

Oui c'est du code un peu compacté ça. :D  
unpack va découper la chaîne de codes hexa (sans espaces, virés une ligne avant) en bouts de deux caractères (soit un octet), map va appliquer chr(hex()) à chaque octet pour transformer le code hexa en caractère et join('', ...) va transformer la suite de caractères (tableau) en chaîne de caractères. :jap:  

Citation :

Je vais modifier tout ça pour dégager les truc "genre content-type: image/png" qui printent du caractère "bizarre", ça nettoiera un peu plus le fichier

C'est à dire bizarre? Je vois rien de bizarre dans le code héxa à première vue, peut-être un problème d'encodage? Ca doit pouvoir se régler.

n°2307227
rotoutou
Across member
Posté le 02-11-2017 à 20:17:07  profilanswer
 


 

rat de combat a écrit :

Oui c'est du code un peu compacté ça. :D  
unpack va découper la chaîne de codes hexa (sans espaces, virés une ligne avant) en bouts de deux caractères (soit un octet), map va appliquer chr(hex()) à chaque octet pour transformer le code hexa en caractère et join('', ...) va transformer la suite de caractères (tableau) en chaîne de caractères. :jap:  

Citation :

Je vais modifier tout ça pour dégager les truc "genre content-type: image/png" qui printent du caractère "bizarre", ça nettoiera un peu plus le fichier

C'est à dire bizarre? Je vois rien de bizarre dans le code héxa à première vue, peut-être un problème d'encodage? Ca doit pouvoir se régler.


 
Pardon quand je dis bizarre c'est qu'à la fin j'ouvre le résultat sous notepad++, les images décodées sont en raw dans le fichier ouvert par défaut en UTF-8, donc ça affiche des carrés pour les caractères de contrôle etc.
 
La conversion semble correcte (je vérifierai demain en ouvrant un des png qui passe par le RP pour voir si c'est vrai)
(et même si y a truc un peu foiré dans cette partie, ce n'est pas grave je m’intéresse surtout aux pages html)
 
no soucÿ  [:augie]


---------------
Reckless inferior depraved repentant ruinous foul-mouthed revered master Rotoutou the great.
n°2307230
rat de com​bat
attention rongeur méchant!
Posté le 02-11-2017 à 23:39:31  profilanswer
 

Ah d'accord, tu parles de fichiers binaires. Oui il faut probablement modifier quelque chose / bricoler avec pack(), j'ai fait le code en pensant uniquement aux fichiers texte. Si tu donnes un exemple de log avec un png ou autre qui passe (et un fichier texte aussi, il faut les deux cas pour tester) je veux bien y jeter un coup d'oeil.


Message édité par rat de combat le 02-11-2017 à 23:40:05
n°2307276
gilou
Modérateur
Modzilla
Posté le 04-11-2017 à 14:58:46  profilanswer
 

Mes deux cents:

Code :
  1. use strict;
  2. use warnings;
  3. use autodie;
  4.  
  5. sub process_data($$) {
  6.    open(my $if, '<', shift);
  7.    open(my $of, '>', shift);
  8.    while (<$if> ) {
  9.         if (/^0x[[:xdigit:]]{4}\s+((?:[[:xdigit:]]{2,4}\s)+)\s/) {
  10.             ($_ = $1) =~ s/\s+//g;
  11.             $_ = pack('H*', $_);
  12.         }
  13.         print $of $_;
  14.    }
  15. }
  16.  
  17. process_data("routoutou.txt", "resultat.txt" );


Et s'il y a du binaire, ouvrir en mode binaire.
binmode($of) après ouverture, et mettre explicitement des "\n" en sortie, tant qu'on a pas détecté qu'on est dans des données binaires.
Mais il faut reconstituer textes globalement avant sinon les lignes splittées entre un \r et un \n causeront problème, cf:
0x0000   4854 5450 2f31 2e31 2032 3030 204f 4b0d        HTTP/1.1.200.OK.
0x0010   0a63 6f6e 7465 6e74 2d6c 656e 6774 683a        .content-length:  
 
 
A+,


Message édité par gilou le 04-11-2017 à 15:51:36

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2307376
rotoutou
Across member
Posté le 07-11-2017 à 15:26:52  profilanswer
 

Merci pour l'aide Gilou :hello:
 
Sinon, pour les trucs en binaire (et autres) que je ne veux pas voir (pas important dans mon contexte) j'ai rajouté ça dans le code de Rat de combat
 


    ...
    if ($buffer=~m/[Cc]ontent-[Tt]ype:\s(image\/png|image\/x-icon|image\/gif|text\/css|application\/x-javascript)/m) {$keep=0};
  }
  else
  {
    print $output_file_handler $buffer if($buffer && $keep);
    ...


 
Par contre si le contenu est dans plusieurs paquets, y a quelques trucs qui passent quand même (pas grave)


---------------
Reckless inferior depraved repentant ruinous foul-mouthed revered master Rotoutou the great.
mood
Publicité
Posté le 07-11-2017 à 15:26:52  profilanswer
 

n°2307398
rat de com​bat
attention rongeur méchant!
Posté le 07-11-2017 à 20:31:40  profilanswer
 

Bien vu gilou le coup du pack(). :jap:  
 

rotoutou a écrit :

Par contre si le contenu est dans plusieurs paquets, y a quelques trucs qui passent quand même (pas grave)

On doit pouvoir éviter les machins binaire complètement en testant chaque bloc/paquet pour voir si il y a des caractères non-imprimables. Dans mon exemple je teste uniquement une partie (<0x1f sauf \t et \n) mais on pourrait rajouter tout ce qui est supérieur à 0x7e.
J'ai des gros doutes quant à l'élégance de mon code mais ça semble fonctionner... :o  

Code :
  1. use strict;
  2. use warnings FATAL=>'all';
  3. use autodie;
  4.  
  5. open my $input, '<', 'input';
  6.  
  7. my $buffer="";
  8. my $last_hex=0;
  9.  
  10. while(<$input> )
  11. {
  12.    if(/^0x[[:xdigit:]]{4}\s+((?:[[:xdigit:]]{2,4}\s+)+)/)
  13.    {
  14.        my $hex=$1;
  15.        $hex=~s/\s+//g;
  16.        $buffer.=pack('H*', $hex); #piqué chez gilou
  17.        $buffer=~s/\r\n/\n/g; #corriger les retours à la ligne
  18.        $last_hex=1;
  19.    }
  20.    else
  21.    {
  22.        if($last_hex) #du code hexa dans la ligne précédente mais plus maintenant -> tout le bloc est passé -> l'imprimer si pas binaire
  23.        {
  24.            $buffer=~s/\n+$//; #virer tout les \n et en rajouter qu'un seul (dans le print)
  25.            print $buffer,"\n" if($buffer && $buffer!~/[\x00-\x08\x0b-\x1f]/); #pas imprimer si caractère ASCII <0x1F sauf \t et \n
  26.            $buffer="";
  27.        }
  28.        $buffer.=$_;
  29.        $last_hex=0;
  30.    }
  31. }
  32. print $buffer if($buffer && $buffer!~/[\x00-\x08\x0b-\x1f]/); #dernier bloc
  33.  
  34. close $input;

n°2307474
rotoutou
Across member
Posté le 08-11-2017 à 20:53:38  profilanswer
 

[:rotoutou:1] bon je prends, mais on va arrêter là : Si un débutant tombe sur un thread comme ça il se suicide  [:albounet]


---------------
Reckless inferior depraved repentant ruinous foul-mouthed revered master Rotoutou the great.
n°2307599
rat de com​bat
attention rongeur méchant!
Posté le 10-11-2017 à 22:18:28  profilanswer
 

rotoutou a écrit :

Si un débutant tombe sur un thread comme ça il se suicide  [:albounet]

Pourquoi ça?
Il n'est pas si horrible que ça mon code quand même. :o :lol:


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

  [Perl] Remplacer plusieurs lignes par le résultat d'un appel externe

 

Sujets relatifs
Reset plusieurs textbox.text sur la même page.[PERL] remplacer un mot dans un fichier
Suppresion dans Appdata sur plusieurs USERSVBA : adapter un userform à plusieurs feuilles
appel au générateur des nombres aleatoire dans un programme c++ Remplacer le contenu d'une colonne dans ma base de donnée SQL
Appel fonction et paramètres variablesVBA word supprimer lignes en doubles
[Perl] Comparaison de fichiers 
Plus de sujets relatifs à : [Perl] Remplacer plusieurs lignes par le résultat d'un appel externe


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