[PERL] Extraire le contenu d'un fichier

cramer -  
 cramer -
Bonjour,

La question que je vous pose a déjà été posé, mais il semblerait que les solutions apportées ne fonctionnent pas chez moi. Je précise quand même que je débute en perl.

Alors voilà, j'ai le fichier suivant :
.................
<cre>
.......................
<type_msg>103</type_msg>
..............
</cre>
................

La balise <cre></cre> peut se répeter indéfiniment et je voudrais extraire dans des fichiers séparés l'ensemble de la balise <cre></cre> en fonction de type_msg, pouvant prendre les valeurs 103,202 ou 204.
Je ne sait pas si celà est important, mais il peut y avoir des espaces, tabulations,sauts de lignes entre les balises.

J'ai donc à partir des réponses du forum fait ceci :

#! /usr/bin/perl

use warnings;use strict;
undef $/;
my $fic = <>;
chomp;
pos($fic)=0;
open(DEST1, ">103.txt");
open(DEST2, ">202.txt");
open(DEST3, ">204.txt");

while ( $fic =~ m/<cre>/gmc ){
print "Lecture du Fichier : \n";
if ($fic =~ / \G(.*?<type_msg>103.*?<\/cre>)/){
print "MT103\n";
print DEST1 $1;
}
if ($fic =~ / \G(.*<type_msg\>202.*<\/cre>)/){
print "MT202\n";
print DEST2 $1;
}
if ($fic =~ / \G(.*<type_msg>204.*<\/cre>)/){
print "MT204\n";
print DEST3 $1;
}

}

close($fic);
close(DEST1);
close(DEST2);
close(DEST3);


mais celà ne fonctionne pas. Il semblerait que le soucis soit au niveau des tests. Pourriez vous m'aider ?

Merci d'avance.

12 réponses

  1. cramer
     
    il semblerait que l'affichage dans "\G" affiche une ',' au lieu d'un point.
    0
  2. blux Messages postés 2051 Date d'inscription   Statut Modérateur Dernière intervention   3 455
     
    Salut,

    un truc m'échappe : tu es obligé de conserver les données que tu as déjà lues pour les mettre dans le bon fichier, vu que la balise type_msg n'est présente qu'au milieu de la balise cre, comment fais-tu ?
    0
  3. cramer
     
    Bonjour,

    oui je suis obligé de conserver les données déjà lues, puisque l'interieur des balises varie en fonction du type_msg. Celà me permet de rediriger tous les 103 dans un fichier, puis de les traiter avec un parser, idem avec les 202 et 204.


    while ( $fic =~ m/<cre>/gmc ){
    print "Lecture du Fichier : \n";
    if ($fic =~ / \G(.*?<type_msg>103.*?<\/cre>)/){


    Pour répondre à ton autre question, justement je ne suis pas sûr que celà soit bon, mais voici pourquoi j'ai fait cà :

    while ( $fic =~ m/<cre>/gmc ){
    print "Lecture du Fichier : \n";
    if ($fic =~ / \G(.*?<type_msg>103.*?<\/cre>)/){


    "m/ ... /gmc", me fait une recherche global dans tous le fichier et multiligne. \G (assertion) me permet de recuperer ce qui commence par
    <cre> et finit par ".*?<type_msg>103.*?</cre>" et de le rediriger. La position est sauvegardé, et on continue le traitement du fichier en recommencant à la balise <cre> suivante.
    0
  4. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    met ton fichier sur cjoint.com et je vais regarder ce soir
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. cramer
     
    D'accord merci.

    Je ne pourrais le mettre que ce soir, étant au travail, cette URL est bloquée :)
    0
  7. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    essai comme ça
    #!/usr/bin/perl
    use strict;use warnings;
    
    open LIRE,"ton_fichier"
      or die "E/S : $!\n";
    
    my (@fic,@res);
    
    while(<LIRE>){
      push @fic,$_ if /<cre>/ .. /<\/cre>/;
    }
    
    @res = split /<\/cre>/, join "",@fic;
    pop @res;
    foreach (@res){
      $_ =~ />(\d{3})</;
      open ECRIRE,">>$1.txt" or die "E/S : $!\n" if $1;
      print ECRIRE "$_</cre>" if $1;
      close ECRIRE;
    }
    
    __END__
    
    0
  8. cramer
     
    D'accord je vais essayer. Merci.

    Voici le fichier original :
    https://www.cjoint.com/?mku712a8jR
    0
    1. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
       
      Ce n'est pas le script que j'ai besoin, mais le fichier à traiter ;-)
      0
  9. cramer
     
    Impressionnant :)

    Celà fonctionne nickel. Je vais tâcher de comprendre cà :)
    Mais de visu si je décide que tout ce qui n'est pas 103,202,204 soit dans un fichier IND, il faut qu'après "$_ =~ />(\d{3})</;"
    je fasse un test comme cà : (débutant en perl, je ne suis pas sur que

    foreach (@res){
    $_ =~ />(\d{3})</;
    if($1 != '103' || $1!='202' || $1!='204')
    {
    open ECRIRE, ">>IND.txt" or die "E/S : $!\n" if $1;
    print ECRIRE "$_</cre>" if $1;
    }
    else
    {
    open ECRIRE,">>$1.txt" or die "E/S : $!\n" if $1;
    print ECRIRE "$_</cre>" if $1;
    close ECRIRE;
    }
    }
    0
    1. blux Messages postés 2051 Date d'inscription   Statut Modérateur Dernière intervention   3 455
       
      Fais gaffe, lami20j est redoutable quand il faut de la syntaxe qu'on dirait un tirage des chiffres et des lettres... :-)
      0
      1. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571 > blux Messages postés 2051 Date d'inscription   Statut Modérateur Dernière intervention  
         
        ;-))
        0
  10. cramer
     
    Arf celà va être plus compliqué :( Bon, je vais tâcher de t'en créer un vite fait. Le voici :

    https://www.cjoint.com/?mkvptvBPUD

    C'est loin d'être le fichier original (le fichier XML original est au taf).
    0
  11. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    #!/usr/bin/perl
    use strict;use warnings;
    
    open LIRE,"toto.txt"
      or die "E/S : $!\n";
    
    my (@fic,@res);
    
    while(<LIRE>){
      push @fic,$_ if /<cre>/ .. /<\/cre>/;
    }
    
    @res = split /<\/cre>/, join "",@fic;
    pop @res;
    foreach (@res){
      $_ =~ />(\d{3})</;
      if ($1 eq 103 || $1 eq 202 || $1 eq 204){
              open ECRIRE,">>$1.txt" or die "E/S : $!\n" if $1;
              print ECRIRE "$_</cre>" if $1;
      } else {
              open IND,">>IND.txt" or die "E/S : $!\n" if $1;
              print IND "$_</cre>" if $1;
      }
      close IND;
      close ECRIRE;
    }
    
    __END__
    
    ou encore
    #!/usr/bin/perl
    use strict;use warnings;
    
    open LIRE,"toto.txt"
      or die "E/S : $!\n";
    
    my (@fic,@res);
    
    while(<LIRE>){
      push @fic,$_ if /<cre>/ .. /<\/cre>/;
    }
    
    @res = split /<\/cre>/, join "",@fic;
    pop @res;
    foreach (@res){
      $_ =~ />(\d{3})</;
      if ($1 =~ /(103|20[24])/){
              open ECRIRE,">>$1.txt" or die "E/S : $!\n" if $1;
              print ECRIRE "$_</cre>" if $1;
      } else {
              open IND,">>IND.txt" or die "E/S : $!\n" if $1;
              print IND "$_</cre>" if $1;
      }
      close IND;
      close ECRIRE;
    }
    
    __END__
    
    0
  12. cramer
     
    Merci à toi lami20j. Tu me tire une belle épingle du pied.
    0