[PERL] Extraire le contenu d'un fichier

Fermé
cramer - 10 déc. 2007 à 10:10
 cramer - 11 déc. 2007 à 08:28
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.
A voir également:

12 réponses

il semblerait que l'affichage dans "\G" affiche une ',' au lieu d'un point.
0
blux Messages postés 26006 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 25 avril 2024 3 289
10 déc. 2007 à 10:25
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
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
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
10 déc. 2007 à 12:43
Salut,

met ton fichier sur cjoint.com et je vais regarder ce soir
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
D'accord merci.

Je ne pourrais le mettre que ce soir, étant au travail, cette URL est bloquée :)
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
10 déc. 2007 à 20:17
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
D'accord je vais essayer. Merci.

Voici le fichier original :
https://www.cjoint.com/?mku712a8jR
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
10 déc. 2007 à 21:07
Ce n'est pas le script que j'ai besoin, mais le fichier à traiter ;-)
0
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
blux Messages postés 26006 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 25 avril 2024 3 289
10 déc. 2007 à 21:16
Fais gaffe, lami20j est redoutable quand il faut de la syntaxe qu'on dirait un tirage des chiffres et des lettres... :-)
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567 > blux Messages postés 26006 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 25 avril 2024
10 déc. 2007 à 22:39
;-))
0
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
Voici un exemple plus sophistiqué :

https://www.cjoint.com/?mkvAcaaQA7
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
10 déc. 2007 à 21:48
#!/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
Merci à toi lami20j. Tu me tire une belle épingle du pied.
0