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

  FORUM HardWare.fr
  Programmation
  Perl

  [perl] Traitement de fichier .csv

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

[perl] Traitement de fichier .csv

n°2001177
grao
The visitor
Posté le 12-06-2010 à 21:15:48  profilanswer
 

Bonjour, j'ai besoin d'aide pour réaliser un script permettant de traiter des fichiers CSV. Je précise que je suis un noob en perl :/
En gros mon script récupère un fichier .csv dont la première ligne sert de header.
Il vérifie que pour chaque ligne:
certains champs sont remplis sinon il les (chaque ligne) envoie  vers un fichier erreur.txt,
remplace le contenu d'un champs si il rencontre une certaine valeur dans ce champs.
Plus d'autres traitements que je détaillerais si besoin.

 

Je rencontre plusieurs problèmes:
Le premier: je souhaite récupérer le fichier .csv à l'aide de Tie::Handle::CSV. Est ce un bon choix où vous me conseillez autre chose?

 

En voulant récupérer le fichier csv je rencontre une erreur: chacune des lignes se termine par ;; apparemment Tie::Handle::CSV kiffe pas trop et du coup s'arrête à la fin de la première ligne.
J'aimerais supprimer les ;; à la fin de chaque ligne mais je vois pas comment faire vu que le problème se situe au moment ou je récupère le fichier.
Si je fais:

Code :
  1. my $csv_fh = Tie::Handle::CSV->new('csv_test.csv', header => 1);
  2. while (my csv_line = <csv_fh> ){
  3.   $csv_line =~ s/;//;
  4.   print $csv_line . "\n\n";
  5. }


Évidemment ça ne marche pas.

 

Toute aide est la bienvenue :jap:


Message édité par grao le 12-06-2010 à 21:38:57

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
mood
Publicité
Posté le 12-06-2010 à 21:15:48  profilanswer
 

n°2001189
grao
The visitor
Posté le 12-06-2010 à 22:01:01  profilanswer
 

Finalement j'ai résolu mon problème: je lis mon fichier et je le modifie à la volée pour supprimer les ; à l'aide de:

Code :
  1. $ligne =~ s/;//g;


J'enregistre le résultat dans un fichier temp puis j'ouvre ce fichier temp avec Tie::Handle::CSV.

 

Maintenant mon soucis et au niveau de l'encodage je pense: lorsque j'affiche le fichier temp avec Tie::Handle::CSV il s'arrête à la première ligne et affiche un � à la place des accents. Le problème est que je ne peux pas me permettre de remplacer les caractères accentués :/
Le csv est généré sous windows et je code sous linux. Vous avez une idée?


Message édité par grao le 12-06-2010 à 22:08:43

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001194
gilou
Modérateur
Modzilla
Posté le 12-06-2010 à 22:23:09  profilanswer
 

Bonsoir,
Quelle est la raison pour laquelle vous utilisez Tie::Handle::CSV plutôt que le module assez standard Text::CSV?
Je vous suggère la lecture de http://perlmeme.org/tutorials/parsing_csv.html
Vos problèmes d'accents sont réglables en précisant l'encoding a l'ouverture du fichier.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001200
grao
The visitor
Posté le 12-06-2010 à 22:48:59  profilanswer
 

Une solution simple: coder sous windows  :o


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001214
grao
The visitor
Posté le 12-06-2010 à 23:27:08  profilanswer
 

gilou a écrit :

Bonsoir,
Quelle est la raison pour laquelle vous utilisez Tie::Handle::CSV plutôt que le module assez standard Text::CSV?
Je vous suggère la lecture de http://perlmeme.org/tutorials/parsing_csv.html
Vos problèmes d'accents sont réglables en précisant l'encoding a l'ouverture du fichier.
A+,


Je trouve l'accès aux champs plus sympa avec Tie::Handle::CSV. :o


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001215
gilou
Modérateur
Modzilla
Posté le 12-06-2010 à 23:35:30  profilanswer
 

grao a écrit :

Une solution simple: coder sous windows  :o

Euh, les modules CPAN sont en général compatibles windows et linux. Donc ce n'est clairement pas une raison valable.
Je ne vois pas pourquoi utiliser un module de type Tie si on n'en a pas les besoins spécifiques (mise a jour incrémentale du fichier, ce qui est couteux en temps d'IO).

grao a écrit :

Je trouve l'accès aux champs plus sympa avec Tie::Handle::CSV. :o

Sauf qu'a partir du moment ou vous faites usages d'un fichier temporaire, l'usage d'un Tie devient complètement inutile (et est couteux)
Pour votre problème d'encodage, il faut probablement faire un
Tie::Handle::CSV->new( 'csv_test.csv', open_mode => '+<:encoding(blablabla)', header => 1);
avec le bon encoding à la place de blablabla (et le bon encoding, il va dépendre de celui de vos données).
A+,


Message édité par gilou le 12-06-2010 à 23:45:44

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001217
grao
The visitor
Posté le 12-06-2010 à 23:46:09  profilanswer
 

L'optimisation n'est clairement pas un de mes objectifs (enfin pour le moment).
Le problème d'encodage vient du fichier .csv qui est généré sous windows, effectivement je pourrais fixer l'encodage mais comme à terme le script est censé tourner sous windows je vais faire au plus simple.
(oui c'est un peu urgent...).

 

Je veux bien éviter d'utiliser Tie::Handle::CSV mais comment accéder à un champ en particulier à partir de mon fichier temp?
Merci du coup de main :jap:
ps: vu mon ancienneté sur le forum tu peux me tutoyer ;)


Message édité par grao le 12-06-2010 à 23:47:19

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001238
gilou
Modérateur
Modzilla
Posté le 13-06-2010 à 09:44:29  profilanswer
 

Il suffit de vous inspirer de ce que j'avais donné en lien:
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Text::CSV;
  5.  
  6. my $file = 'prospects.csv';
  7.  
  8. my $csv = Text::CSV->new();
  9.  
  10. open (CSV, "<", $file) or die $!;
  11.  
  12. while (<CSV> ) {
  13.    next if ($. == 1);
  14.    if ($csv->parse($_)) {
  15.        my @columns = $csv->fields();
  16.        print "Name: $columns[0]\n\tContact: $columns[4]\n";
  17.    } else {
  18.        my $err = $csv->error_input;
  19.        print "Failed to parse line: $err";
  20.    }
  21. }
  22. close CSV;


le  next if ($. == 1); sert a sauter la première ligne, qui contient le nom des champs dans leur exemple.
Vous n'en avez pas besoin peut être, mais a ce niveau, vous pouvez rejeter les lignes vides, puis virer ;; de la fin des lignes:
En modifiant cela pour le rendre plus clean:

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Text::CSV;
  5.  
  6. my $filename = 'prospects.csv';
  7. my $csv = Text::CSV->new();
  8. open (my $file, "<", $filename) or die $!;
  9. while (<$file> ) {
  10.    next if ($. == 1);
  11.    next if (/^\s*$/);
  12.    s/;;$//;
  13.    if ($csv->parse($_)) {
  14.        my @columns = $csv->fields();
  15.        print "| ", join(" | ", @columns), " |\n";
  16.    } else {
  17.        my $err = $csv->error_input;
  18.        print "Failed to parse line: $err";
  19.    }
  20. }
  21. close $file;


Pour le open, un <:encoding(xxx) peut s'avérer utile vu ce que vous avez dit plus haut.
Bon, quand vous avez vos champs dans @columns, il ne vous reste plus que bosser avec.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001262
grao
The visitor
Posté le 13-06-2010 à 11:35:01  profilanswer
 

Merci beaucoup :jap:
Bon apparemment à première vue aucune ligne ne passe correctement, il me sort "Failed to parse line" pour toute les lignes.
Faut dire le csv est pas super propre toutes les lignes ressemblent à ""blabla"",""toto"", etc... et même parfois j'ai du texte avec des virgules qui foutent la merde: ""blabla, blabla"",""toto"", etc...
Je vais regarder ça de plus près.

 

EDIT: en regardant plus attentivement le lien au dessus, il semblerait qu'il y ait de quoi résoudre tout mes problèmes...


Message édité par grao le 13-06-2010 à 12:06:33

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001269
grao
The visitor
Posté le 13-06-2010 à 12:30:28  profilanswer
 

En fait tout vient du soft qui sort le csv, il respecte pas le standard.
Chaque ligne ressemble à ça:
"toto,""titi, tata"",""plop"",""tutu""";;;

 

Notez le " en début de ligne et le """ sur le dernier champs.
L'option allow_loose_quotes pourrait régler le problème: "there is a way to get that parsed, and leave the quotes inside the quoted field as-is. This can be achieved by setting allow_loose_quotes AND making sure that the escape_char is not equal to quote_char."
Seulement dans ce cas comment faire en sorte qu'une virgule du style ""titi,toto"" ne soit pas interprétée comme le séparateur?


Message édité par grao le 13-06-2010 à 13:49:09

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
mood
Publicité
Posté le 13-06-2010 à 12:30:28  profilanswer
 

n°2001278
grao
The visitor
Posté le 13-06-2010 à 14:02:53  profilanswer
 

Pour l'encodage j'ai à moitié solutionné le problème: quand je mets un encodage windows style windows-1258 à peu près la moitié du fichier passe (y compris certaines lignes avec des accents) mais pas l'autre qui comprend pourtant les mêmes lettres accentuées :??:
J'ai essayé avec différends encodages ça donne la même chose.

 

EDIT: ce n'était pas un problème d'encodage: dans une des lignes il y avait un ; qui se baladait. Du coup je supprime tous les ; du fichier et il me parse tout le fichier tranquille. J'ai plus qu'à faire mes traitements.
Merci du coup de main. (enfin bon j'ai pas encore terminé...)
Gilou si tu passes sur Paris prochainement je te paye une bière :jap:


Message édité par grao le 13-06-2010 à 14:15:56

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001284
gilou
Modérateur
Modzilla
Posté le 13-06-2010 à 14:48:27  profilanswer
 

Une Chimay!! [:cacao lion]  
 
J'ai pas plus répondre plus tôt, je cueillais les cerises sur l'arbre ce matin :)
 
Notes que si tu veux tout controller au niveau du parsing, tu peux faire

Code :
  1. s/;;$//;
  2.    chop $_;
  3.    my @columns = split /,/, $_;
  4.  .........


et n'utiliser aucun module (bref, virer le use Text::CSV;)
Ça sera peut être un poil plus lent, mais la tu contrôles entièrement ce qui se passe.
Typiquement, tu peux vérifier si le nb de champs trouvés est subitement différent de celui attendu.
Un split /,;/, $_; aurait permis de considérer , ou bien ; comme séparateur de champ (si le ; inattendu était une erreur pour un , et que d'autres peuvent survenir)
A+,

Message cité 1 fois
Message édité par gilou le 13-06-2010 à 14:52:51

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001289
grao
The visitor
Posté le 13-06-2010 à 15:03:01  profilanswer
 

gilou a écrit :

Une Chimay!! [:cacao lion]

 

J'ai pas plus répondre plus tôt, je cueillais les cerises sur l'arbre ce matin :)

 

Notes que si tu veux tout controller au niveau du parsing, tu peux faire

Code :
  1. s/;;$//;
  2.    chop $_;
  3.    my @columns = split /,/, $_;
  4.  .........


et n'utiliser aucun module (bref, virer le use Text::CSV;)
Ça sera peut être un poil plus lent, mais la tu contrôles entièrement ce qui se passe.
Typiquement, tu peux vérifier si le nb de champs trouvés est subitement différent de celui attendu.
Un split /,;/, $_; aurait permis de considérer , ou bien ; comme séparateur de champ (si le ; inattendu était une erreur pour un , et que d'autres peuvent survenir)
A+,


Monsieur est connaisseur, pour mois ce sera une bush :o
Merci beaucoup pour le code je vais tester tout ça :jap:


Message édité par grao le 13-06-2010 à 15:33:17

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001292
grao
The visitor
Posté le 13-06-2010 à 15:34:47  profilanswer
 

En revanche il y a un truc que je pige pas avec Text::CSV après avoir parsé le fichier je souhaite afficher un champs en particulier seulement il met l'intégralité de la ligne dans $columns[0]. $columns[1] et suivant sont vides.


Message édité par grao le 13-06-2010 à 15:37:46

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001299
gilou
Modérateur
Modzilla
Posté le 13-06-2010 à 15:57:45  profilanswer
 

Tu peux copier ici
1) deux ou trois lignes de ton fichier exemple pour test
2) le bout de code perl que tu as
Que je voie ce qui cloche
A+,


Message édité par gilou le 13-06-2010 à 15:58:15

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001300
grao
The visitor
Posté le 13-06-2010 à 16:00:50  profilanswer
 

J'ai trouvé la solution ultime: Virer tous les " de mon fichier à l'aide d'un s/"//g;
Et hop j'accède à tous mes champs comme je veux :o

 
Code :
  1. #!/usr/bin/perl
  2.     use strict;
  3.     use warnings;
  4.     use Text::CSV;
  5.     my $file = 'RFO(brut)test.txt';
  6.     my $csv = Text::CSV->new();
  7.     open (CSV, "<", $file) or die $!;
  8. my $temp = 'tempmodele';
  9. open(TEMP,'>',$temp);
  10.     while (<CSV> ) {
  11.  next if ($. == 1);
  12.  s/;//g;
  13.  s/"//g;
  14.  if ($csv->parse($_)) {
  15.             my @columns = $csv->fields();
  16.             print TEMP "Ticket:" . $columns[0] . "No" . $columns[1] ."\n";
  17.         } else {
  18.             my $err = $csv->error_input;
  19.             print "Failed to parse line: $err";
  20.         }
  21.     }
  22.     close CSV;


L'affichage sur la console m'indique que des erreurs de parse dues à l'encodage mais mon fichier tempmodele (qui me sert d'affichage de test) est nickel.
je vais enfin pouvoir avancer.
Je t'en dois 2 :jap:


Message édité par grao le 13-06-2010 à 16:10:33

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001307
grao
The visitor
Posté le 13-06-2010 à 16:28:12  profilanswer
 

Bon c'est pas la solution miracle parce que dans certains champs j'ai du texte avec une ou des , du coup ça décale mes $columns[x] et fait foirer mes tests.
Comment gérer l'échappement des , intra-champs?
Il faudrait garder les " pour le faire mais ça coince au parsing :/
EDIT: s/""/'/g; simplement.
Au passage comment tester si un champ est vide? J'ai essayer if(! defined $columns[11]) et if(! exists $columns[11]) mais j'ai plein de faux positifs, if( $columns[11] eq '') génère une erreur :/


Message édité par grao le 13-06-2010 à 16:54:15

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001319
gilou
Modérateur
Modzilla
Posté le 13-06-2010 à 17:41:22  profilanswer
 

A priori, je ferais:
if ((not defined $columns[11]) or ($columns[11] eq "" ))
Soit c'est pas défini (on a trouvé moins de champs), soit le champ est vide.
 
Tu peux copier ici quelques lignes de ton fichier de données, ou c'est trop confidentiel?
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001320
grao
The visitor
Posté le 13-06-2010 à 17:48:29  profilanswer
 

Voici des lignes (dont j'ai changé les valeurs biensur):
"Champs1,""Champs2"",""Champs3"",""Champs4"",""Champs5""";;
"BLABLA,""qsdqd2454"",""dqfqd@qdq.fr"",""05/32/2010"",""qzerqzef,qzffd""";;
"BLOBLO,""zdf54"",""dqfqf@qdq.fr"",""05/32/2010"",""sdfsdf"",""""";;

 

Je pense que le problème vient du parsing: le premier champs fait chier parce qu'il commence par " mais il en manque un à la fin, en fait il est à la fin de la ligne :/
Sans compter le problème de la , en milieu du champs 5 qui fait que dans les lignes ou je teste un champs après un comportant une , il décale tout.

 

Mon code:

Code :
  1. #!/usr/bin/perl
  2.     #use strict;
  3.     use warnings;
  4.     use Text::CSV;
  5.     my $file = 'RFO(brut)test.txt';
  6.     my $csv = Text::CSV->new();
  7.     open (CSV, "<", $file) or die $!;
  8. my $temp = 'tempmodele.txt';
  9. open(TEMP,'>',$temp);
  10.     while (<CSV> ) {
  11.  next if ($. == 1);
  12.  s/;//g;
  13.  #s/""/'/g;
  14.  s/"""""/""""/g;
  15.  if ($csv->parse($_)) {
  16.             my @columns = $csv->fields();
  17.    print TEMP "| ", join(" | ", @columns), " |\n";
  18.         } else {
  19.             my $err = $csv->error_input;
  20.             print "Failed to parse line: $err";
  21.         }
  22.     }
  23.     close CSV;
 

Voila ce que j'ai dans mon fichier de test:
| BLABLA,"qsdqd2454","dqfqd@qdq.fr","05/32/2010","qzerqzef,qzffd" |
| BLOBLO,"zdf54","dqfqf@qdq.fr","05/32/2010","sdfsdf","" |

 


La première ligne est considérée comme un header par Text::CSV.

 

Idéalement j'aimerais quelque chose du style:
| "BLABLA","qsdqd2454","dqfqd@qdq.fr","05/32/2010","qzerqzef,qzffd" |

 

Par ailleurs si je fais un print $columns[0] il me renvoie toute la ligne au lieu du premier champs. C'est pour ça que je pense que tout le problème vient de ce premier champs.

 

Si je suis pas clair faut le dire :whistle:

Message cité 1 fois
Message édité par grao le 13-06-2010 à 18:10:18

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001336
gilou
Modérateur
Modzilla
Posté le 13-06-2010 à 20:00:17  profilanswer
 

grao a écrit :

Voici des lignes (dont j'ai changé les valeurs biensur):
"Champs1,""Champs2"",""Champs3"",""Champs4"",""Champs5""";;
"BLABLA,""qsdqd2454"",""dqfqd@qdq.fr"",""05/32/2010"",""qzerqzef,qzffd""";;
"BLOBLO,""zdf54"",""dqfqf@qdq.fr"",""05/32/2010"",""sdfsdf"",""""";;

Il y a que 5 champs dans le header et 6 dans les lignes, est-ce bien normal, ou une erreur a la recopie?
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001338
gilou
Modérateur
Modzilla
Posté le 13-06-2010 à 20:27:33  profilanswer
 

Sinon, en rajoutant un champ 6 dans le header, ce script passe assez bien sur votre exemple:
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my $filename = 'csv1.txt';
  6. open (my $file, "<", $filename) or die $!;
  7. my $fields = 0;
  8. while (<$file> ) {
  9.    chop $_; #on vire le retour chariot final
  10.    s/;;$//; #on vire les ;; en fin de ligne
  11.    # on recupere le nombre de champs a partir de la première ligne
  12.    if ($. == 1) {
  13.        my @columns = split /,/, $_;
  14.        $fields = $#columns;
  15.        next;
  16.    }
  17.    # on saute les lignes vides
  18.    next if (/^\s*$/);
  19.    # découpage en champs
  20.    my @columns = split /,/, $_;
  21.    # Le découpage est il bon?
  22.    if (not ($#columns == $fields)) {
  23.        print "Incorrect fields number for line $.: $_\n";
  24.        next;
  25.    }
  26.    # on vire les " autour de chaque champ
  27.    map {s/^"+|"+$//g} @columns;
  28.    # on exploite les champs
  29.    print "| ", join(" | ", @columns), " |\n";
  30. }
  31. close $file;


A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001339
grao
The visitor
Posté le 13-06-2010 à 20:43:32  profilanswer
 

J'avais donné les champs pour exemple, j'avais pas fais attention au nombre ;)
Merci pour le code.
J'ai réussi finalement en nettoyant le csv dans l'ordre de cette manière:

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Text::CSV_XS;
  5. my $filename = 'RFO(brut).csv';
  6. my $csv = Text::CSV_XS->new();
  7. open(CSV_INPUT, "<:encoding(windows-1252)", $filename) or die $!;
  8. my $temp = "temp.txt";
  9. open(TEMP,'>',$temp);
  10. while (my $ligne = <CSV_INPUT> ) {
  11.     next if ($. == 1);
  12.     #next if (/^\s*$/);
  13.     $ligne =~ s/";//g;
  14.     $ligne =~ s/""/"/g;
  15.     $ligne =~ s/;//g;
  16.     $ligne = substr($ligne, 1);
  17.     if ($csv->parse($ligne)) {
  18.         my @columns = $csv->fields();
  19.                   print TEMP "@columns \n";
  20.                   print TEMP "$columns[11] \n";
  21.       } 
  22.     }
  23. }


 
Tout fonctionne comme je veux. Tous mes champs sont présents et dans l'ordre.
Je peux faire mes traitements.
 
Après cela j'enverrais chaque ligne par mail.
Quelque chose me dit que la génération et l'envoi des mails risquent d'être sympathiques aussi...
Gilou si tu tiens vraiment à tes binouzes je n'ai qu'une parole :o


Message édité par grao le 13-06-2010 à 20:44:49

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2001340
gilou
Modérateur
Modzilla
Posté le 13-06-2010 à 21:14:10  profilanswer
 

Ça manque de close après les open, ce code...
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2001342
grao
The visitor
Posté le 13-06-2010 à 21:17:29  profilanswer
 

Ils y sont, j'ai juste pas copié jusqu'en bas :)


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2002040
grao
The visitor
Posté le 16-06-2010 à 09:53:07  profilanswer
 

Je voudrais savoir si il existe un moyen de n'exécuter une instruction dans une boucle qu'une seule fois. ex:
while (my $ligne = <CSV_INPUT> ) {
         print "Liste des groupes"; #à n'executer qu'une fois
         print $columns[indice du groupe] # je simplifie...
}

 

Je pourrais stocker un boolean et faire un test dessus à chaque itération mais je me demande si il existe un mot clé du langage.
Merci.


Message édité par grao le 16-06-2010 à 10:08:50

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2002104
gilou
Modérateur
Modzilla
Posté le 16-06-2010 à 11:29:42  profilanswer
 

C'était écrit plus haut:
if ($. == 1) {...}
$. c'est le numéro de ligne du fichier en cours de lecture.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2002118
grao
The visitor
Posté le 16-06-2010 à 11:59:18  profilanswer
 

gilou a écrit :

C'était écrit plus haut:
if ($. == 1) {...}
$. c'est le numéro de ligne du fichier en cours de lecture.
A+,


Oui mais ce n'est pas ce que je demande.
Je souhaite executer une seule fois: print "Liste des groupes";
Puis pour chaque ligne: print $columns[indice du groupe] # je simplifie...

 

"Liste des groupes" n'est pas contenu dans mon fichier en lecture, c'est moi qui l'ajoute dans ma sortie pour faire la mise en page.

 

Sauf que je ne veux pas afficher:
"Liste des groupes"
"groupe1"
"Liste des groupes"
"groupe2"

 

Mais:
"Liste des groupes"
"groupe1"
"groupe2"

 

Le tout sans mettre print "Liste des groupes"; avant la boucle parce que je veux mettre un titre pour chaque champ.

Message cité 1 fois
Message édité par grao le 16-06-2010 à 11:59:32

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2002124
gilou
Modérateur
Modzilla
Posté le 16-06-2010 à 12:11:33  profilanswer
 

grao a écrit :


Oui mais ce n'est pas ce que je demande.
Je souhaite executer une seule fois: print "Liste des groupes";
Puis pour chaque ligne: print $columns[indice du groupe] # je simplifie...

Il faudra m'expliquer pourquoi  
if ($. == 1) {print "Liste des groupes";}  
ne colle pas pour vous, car c'est exactement ce que ça fait.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2002140
grao
The visitor
Posté le 16-06-2010 à 12:35:05  profilanswer
 

Effectivement, OTAN pour moi :jap:


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2002453
grao
The visitor
Posté le 17-06-2010 à 11:33:59  profilanswer
 

J'ai quasiment fini: seulement j'ai un soucis avec l'envoi de mail.
Voici mon code:

Code :
  1. #send mail
  2.  $smtp->mail('expediteur@toto.com');
  3.  $smtp->to('destinataire@titi.com');
  4.  $smtp->data();
  5.  $smtp->datasend($mail_final);
  6.  $smtp->dataend();
  7.  $smtp->quit();


 
Le mail est bien envoyé (et reçu :D ) seulement le code HTML n'est pas interprété, il affiche le code "brut".
Ma variable $mail_final contient le contenu du mail de cette façon: <html> le code html du mail </html>.
 
J'imagine que j'ai oublié un petit truc de rien du tout mais je vois pas quoi...

Message cité 1 fois
Message édité par grao le 17-06-2010 à 11:36:35

---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2002457
grao
The visitor
Posté le 17-06-2010 à 11:46:27  profilanswer
 

grao a écrit :

J'ai quasiment fini: seulement j'ai un soucis avec l'envoi de mail.
Voici mon code:

Code :
  1. #send mail
  2.  $smtp->mail('expediteur@toto.com');
  3.  $smtp->to('destinataire@titi.com');
  4.  $smtp->data();
  5.  $smtp->datasend($mail_final);
  6.  $smtp->dataend();
  7.  $smtp->quit();


 
Le mail est bien envoyé (et reçu :D ) seulement le code HTML n'est pas interprété, il affiche le code "brut".
Ma variable $mail_final contient le contenu du mail de cette façon: <html> le code html du mail </html>.
 
J'imagine que j'ai oublié un petit truc de rien du tout mais je vois pas quoi...


Trouvé: il faut ajouter la ligne: $smtp->datasend("Content-Type: text/html\n\n" ); avant $smtp->datasend($mail_final);


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2002809
nono 63
Posté le 18-06-2010 à 16:04:37  profilanswer
 

Si je peux me permettre, je viens me greffer sur la discussion.
J'utilise le module Text::CSV_XS pour parser mon CSV.
Le hic c'est que je souhaite "filtrer" par un regex les champs avant de les mettre dans mon tableau. Et là je coince
 

Code :
  1. while (<FIC> ) {
  2.  $_ =~ m/>(.+?)</g;
  3.  $csv->parse($_) or die "parse() failed: " . $csv->error_input();
  4.         my @data = $csv->fields();
  5.  }
  6.  for my $i (0..$#data) {
  7.         push @{$columns[$i]}, $data[$i];
  8.      }


Y'a t'il une solution avec ce module ou faut-il faire le "parse" manuellement ?


---------------
Mon topic Achat/ventes : http://forum.hardware.fr/hfr/Achat [...] 2496_1.htm
n°2002851
grao
The visitor
Posté le 18-06-2010 à 17:34:04  profilanswer
 

Gilou j'ai un soucis avec la vaiable $.
Je l'utilise dans plusieurs boucles seulement j'ai l'impression qu'elle n'est pas réinitialisée entre chacune d'elles.  
Du coup la deuxième fois (ou même après) quand je fais next if ($. == 1 ); il ne saute pas la première ligne.
Si je fais dans ma deuxième boucle un print $. il commence à 345 :o
C'est une variable propre à chaque boucle ou globale pour le fichier?


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2002875
gilou
Modérateur
Modzilla
Posté le 18-06-2010 à 20:04:07  profilanswer
 

C'est une variable propre au filehandle, pas a une boucle donnée, qui donne le numéro de ligne lue.
Si tu as besoin d'une variable comptant les tours de boucle, dans une boucle pas liée à la lecture d'un fichier, tu te la crée, c'est simple.
Bon, selon ce sur quoi on boucle et le type de boucle, il y a certains hacks qui marchent, mais il n'y a rien de général.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2002878
gilou
Modérateur
Modzilla
Posté le 18-06-2010 à 20:10:40  profilanswer
 

nono 63 a écrit :

Si je peux me permettre, je viens me greffer sur la discussion.
J'utilise le module Text::CSV_XS pour parser mon CSV.
Le hic c'est que je souhaite "filtrer" par un regex les champs avant de les mettre dans mon tableau. Et là je coince
 

Code :
  1. while (<FIC> ) {
  2.  $_ =~ m/>(.+?)</g;
  3.  $csv->parse($_) or die "parse() failed: " . $csv->error_input();
  4.         my @data = $csv->fields();
  5.  }
  6.  for my $i (0..$#data) {
  7.         push @{$columns[$i]}, $data[$i];
  8.      }


Y'a t'il une solution avec ce module ou faut-il faire le "parse" manuellement ?


Une fois que vous avez @data, rien ne vous empêche d'en modifier le contenu, ou bien de modifier un $data[$i] avant le push.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2002899
grao
The visitor
Posté le 18-06-2010 à 21:34:28  profilanswer
 

gilou a écrit :

C'est une variable propre au filehandle, pas a une boucle donnée, qui donne le numéro de ligne lue.
Si tu as besoin d'une variable comptant les tours de boucle, dans une boucle pas liée à la lecture d'un fichier, tu te la crée, c'est simple.
Bon, selon ce sur quoi on boucle et le type de boucle, il y a certains hacks qui marchent, mais il n'y a rien de général.
A+,


Ok merci. Je vais faire ça à la main :jap:


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
n°2003481
nono 63
Posté le 21-06-2010 à 18:46:59  profilanswer
 

gilou a écrit :


Une fois que vous avez @data, rien ne vous empêche d'en modifier le contenu, ou bien de modifier un $data[$i] avant le push.
A+,


ok j'essaye comme ça mais il doit me manquer une astuce car mon regex ne s'applique pas :

Code :
  1. for my $i (0..$#data) {
  2. $data[$i] =~ m/>([^\;]+?)</;
  3.         push (@resul, $data[$i]);
  4.      }


le contenu de $data[0] par exemple étant <Titi>valeur</Titi>
 :pt1cable:


---------------
Mon topic Achat/ventes : http://forum.hardware.fr/hfr/Achat [...] 2496_1.htm
n°2003485
gilou
Modérateur
Modzilla
Posté le 21-06-2010 à 19:14:51  profilanswer
 

A l'oeil nu, le regexp est faux.
Vous voulez matcher quoi dans votre expression?
Le fait qu'il y a du texte entre deux balises? Ca devrait être
m/\>[^<]+\</;
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2003736
nono 63
Posté le 22-06-2010 à 15:01:20  profilanswer
 

C'est exact  :jap:  
Je souhaitais extraire le texte entre les 2 balises mais je ne savais pas qu'il fallait échapper les <>. Merci


---------------
Mon topic Achat/ventes : http://forum.hardware.fr/hfr/Achat [...] 2496_1.htm
n°2004301
grao
The visitor
Posté le 23-06-2010 à 22:39:53  profilanswer
 

Sinon j'ai testé les tables de hashage en Perl, c'est plutôt performant...


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

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

  [perl] Traitement de fichier .csv

 

Sujets relatifs
[perl] envoie de trap SNMPv3[RESOLU] [SHELL] extraction et reformattage des données d'un fichier
[Resolu] Ouvrir un fichier ".csv" par macro proprementEnregistrement d'un fichier texte dans une procédure récursive
Parseur XML (fichier récupéré à partir d'un web service)enigme de \n en perl
problème de création de fichier dll sous 64 bitstester l'existence d'un fichier et plus
Plus de sujets relatifs à : [perl] Traitement de fichier .csv


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