[perl] Traitement de fichier .csv

Traitement de fichier .csv [perl] - Perl - Programmation

Marsh Posté le 12-06-2010 à 21:15:48    

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.
Reply

Marsh Posté le 12-06-2010 à 21:15:48   

Reply

Marsh Posté le 12-06-2010 à 22:01:01    

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.
Reply

Marsh Posté le 12-06-2010 à 22:23:09    

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é!  --
Reply

Marsh Posté le 12-06-2010 à 22:48:59    

Une solution simple: coder sous windows  :o


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
Reply

Marsh Posté le 12-06-2010 à 23:27:08    

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.
Reply

Marsh Posté le 12-06-2010 à 23:35:30    

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é!  --
Reply

Marsh Posté le 12-06-2010 à 23:46:09    

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.
Reply

Marsh Posté le 13-06-2010 à 09:44:29    

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é!  --
Reply

Marsh Posté le 13-06-2010 à 11:35:01    

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.
Reply

Marsh Posté le 13-06-2010 à 12:30:28    

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.
Reply

Marsh Posté le 13-06-2010 à 12:30:28   

Reply

Marsh Posté le 13-06-2010 à 14:02:53    

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.
Reply

Marsh Posté le 13-06-2010 à 14:48:27    

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é!  --
Reply

Marsh Posté le 13-06-2010 à 15:03:01    

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.
Reply

Marsh Posté le 13-06-2010 à 15:34:47    

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.
Reply

Marsh Posté le 13-06-2010 à 15:57:45    

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é!  --
Reply

Marsh Posté le 13-06-2010 à 16:00:50    

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.
Reply

Marsh Posté le 13-06-2010 à 16:28:12    

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.
Reply

Marsh Posté le 13-06-2010 à 17:41:22    

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é!  --
Reply

Marsh Posté le 13-06-2010 à 17:48:29    

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.
Reply

Marsh Posté le 13-06-2010 à 20:00:17    

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é!  --
Reply

Marsh Posté le 13-06-2010 à 20:27:33    

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é!  --
Reply

Marsh Posté le 13-06-2010 à 20:43:32    

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.
Reply

Marsh Posté le 13-06-2010 à 21:14:10    

Ç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é!  --
Reply

Marsh Posté le 13-06-2010 à 21:17:29    

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


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
Reply

Marsh Posté le 16-06-2010 à 09:53:07    

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.
Reply

Marsh Posté le 16-06-2010 à 11:29:42    

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é!  --
Reply

Marsh Posté le 16-06-2010 à 11:59:18    

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.
Reply

Marsh Posté le 16-06-2010 à 12:11:33    

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é!  --
Reply

Marsh Posté le 16-06-2010 à 12:35:05    

Effectivement, OTAN pour moi :jap:


---------------
Recherche affiche de GITS Arise 3 et 4, faire offre.
Reply

Marsh Posté le 17-06-2010 à 11:33:59    

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.
Reply

Marsh Posté le 17-06-2010 à 11:46:27    

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.
Reply

Marsh Posté le 18-06-2010 à 16:04:37    

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
Reply

Marsh Posté le 18-06-2010 à 17:34:04    

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.
Reply

Marsh Posté le 18-06-2010 à 20:04:07    

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é!  --
Reply

Marsh Posté le 18-06-2010 à 20:10:40    

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é!  --
Reply

Marsh Posté le 18-06-2010 à 21:34:28    

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.
Reply

Marsh Posté le 21-06-2010 à 18:46:59    

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
Reply

Marsh Posté le 21-06-2010 à 19:14:51    

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é!  --
Reply

Marsh Posté le 22-06-2010 à 15:01:20    

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
Reply

Marsh Posté le 23-06-2010 à 22:39:53    

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.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed