[PERL] Extraire le contenu d'un fichier
cramer
-
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.
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:
- [PERL] Extraire le contenu d'un fichier
- Fichier bin - Guide
- Comment réduire la taille d'un fichier - Guide
- Comment ouvrir un fichier epub ? - Guide
- Fichier rar - Guide
- Extraire une video youtube - Guide
12 réponses
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 ?
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 ?
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.
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.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Salut,
essai comme ça
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__
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;
}
}
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;
}
}
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).
https://www.cjoint.com/?mkvptvBPUD
C'est loin d'être le fichier original (le fichier XML original est au taf).
#!/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__