Demande d'aide : Manipulation de fichier texte en .csv

Demande d'aide : Manipulation de fichier texte en .csv - Perl - Programmation

Marsh Posté le 31-08-2011 à 12:16:18    

Bonjour à tous  
 
Petite présentation:
Je suis Administrateur réseau et je gère environ 100 postes ainsi que 3 serveurs. ( Windows server 2008 et 2003 )
Je connais bien windows server ainsi que le réseau mais je m'y connais beaucoups moins en programmation. Je fais un peu de batch Windows & Linux mais que des choses simples ( à comparé de vous les programmeurs ).
Je me penche plus du coté de la virtualisation ( ESXI, Hyper-V , Xenserver ) et de la haute disponibilité avec les SAN et le clustering que vers la programmation.  
 
Mon problème :
Mon DSI m'à demander de réaliser une routine ( un script ou autre ) pour retoucher et convertir un fichier de compta qui provient d'une vieille machine UNIX.
Il s'agit d'un fichier .dat que l'on peut editer avec un notepad ou excel et que l'on veut transformer en .csv
Ce fichier est rempli d'information inutiles... un exemple vos mieux qu'un long discours, voici un extrait de ce fichier :
 
 
 ********************************************************************************
000008   Risque aut.    45KF  *
  LCR 60 J FM
************************************************************************************************************************
! ECR. !  DATE  ! NAT ! LIBELLE ECRITURE  *  JAL  ! PIECE  D'ORIGINE                *    DEBIT      !   CREDIT      !LT!
************************************************************************************************************************
!055117!11 10 10  FA    FACTURE           *       055117       ECHEANCE 31 12 10    *       1 272.63!               !  !
!055334!18 10 10  FA    FACTURE           *       055334       ECHEANCE 31 12 10    *         186.52!               !  !
!055745!29 10 10  FA    FACTURE           *       055745       ECHEANCE 31 12 10    *         563.59!               !  !
------------------------------------------------------------------------------------------------------------------------
TOTAL CLIENT   DEBIT :           2 022.74    CREDIT :               0.00      SOLDE :       2 022.74
 
 
*********************************************************************************
000012     15KF  *
  LCR 60 J FM
************************************************************************************************************************
! ECR. !  DATE  ! NAT ! LIBELLE ECRITURE  *  JAL  ! PIECE  D'ORIGINE                *    DEBIT      !   CREDIT      !LT!
************************************************************************************************************************
!055111!11 10 10  FA    FACTURE           *       055111       ECHEANCE 31 12 10    *         188.13!               !  !
!055546!22 10 10  FA    FACTURE           *       055546       ECHEANCE 31 12 10    *         345.05!               !  !
------------------------------------------------------------------------------------------------------------------------
TOTAL CLIENT   DEBIT :             533.18    CREDIT :               0.00      SOLDE :         533.18
 
 
 
 
Et donc nous reprenons ce fichier manuellement tous les mois pour qu'il ressemble a ceci dans un Excel :
 
 
N°       N° écriture  Date/écriture Nature Libellé     Code journal N° de facture Date/d'échéance Débit Crédit
8 55117 11/10/2010 FA FACTURE  55117 31/12/2010 1 272.63  
8 55334 18/10/2010 FA FACTURE  55334 31/12/2010 186.52  
8 55745 29/10/2010 FA FACTURE  55745 31/12/2010 563.59  
12 55111 11/10/2010 FA FACTURE  55111 31/12/2010 188.13  
12 55546 22/10/2010 FA FACTURE  55546 31/12/2010 345.05  
 
 
Il faut donc le sortir sous un format csv  
Avec :  
- Le N° de compte
- Le N° d'ecriture
- La date de l'ecriture
- La nature
- Le Libellé
etc....
en l'ayant, bien entendu, purgé de tout ces caratères inutile.
 
J'ai cherché des journées entières mais je ne sais meme pas quelle langage serait le plus approprié et le temps qu'il me faudrait pour l'apprendre ......
 
Avec le nombre de programmeur qu'il y a ici je me suis dit que quelqu'un pourrait avoir une idée car cela dépasse ( et de très loin) mes compétences.
 
Très cordialement
 
 
CPSeb


Message édité par gilou le 12-09-2011 à 16:59:25
Reply

Marsh Posté le 31-08-2011 à 12:16:18   

Reply

Marsh Posté le 01-09-2011 à 19:23:25    

Sous Linux, je t'aurais recommandé Awk, mais rien de tel à ma connaissance sous Windows.
 
Comme langage de script avec des fonctions de manipulation de texte évoluées, y'a Perl et Php. Pour rappel, php ne sert pas qu'à faire des sites web, il permet aussi d'effecteur tout type de traitement (même d'image) et peut être appelé en ligne de commande ;)
 
Avec des fonction de type file() (pour lire tout le fichier et mettre chaque ligne dans un tableau),  explode() et str_replace(), ça sevrait le faire ;) Sans oublier file_put_content() pour sauvegarder le tout dans un fichier.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 01-09-2011 à 19:32:19    

rufo a écrit :

Sous Linux, je t'aurais recommandé Awk, mais rien de tel à ma connaissance sous Windows.


Awk avec Cygwin. Ou Powershell, sous Windows.


PHP  [:everything4free]

 

Perl oui, Python oui, Ruby oui, mais pas PHP :/

 

CPSeb: probablement pas de langage fondamentalement mieux qu'un autre, sauf si tu en trouves un qui sait nativement parser ton format de rapport bizarre mais ça j'en doute. Je serais toi, je regarderais du côté de Ruby ou Python, ils sont lisibles et ont un bon support Windows. Sinon, comme je l'ai mentionné, regardes du côté de powershell dans la mesure où tu es sous windows, je ne sais pas ce que ça donne niveau string munging mais ça peut suffire.


Message édité par masklinn le 01-09-2011 à 19:37:21

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 01-09-2011 à 23:18:25    

Masklinn, un peu bizarre que tu dises oui à Perl et non à Php :??: La syntaxe est assez proche et qq'un qui a fait l'un, passe très facilement à l'autre...


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 02-09-2011 à 07:03:30    

rufo a écrit :

Masklinn, un peu bizarre que tu dises oui à Perl et non à Php :??:


Non. Perl a une très grande librairie tierce (CPAN), des fonctions natives très orthogonales, une syntaxe littérale pour les regex et un excellent support pour tout ce qui est manipulation de chaînes.
 
PHP est un grand sac de merde.

rufo a écrit :

La syntaxe est assez proche et qq'un qui a fait l'un, passe très facilement à l'autre...


C'est une blague? La seule relation syntactique entre PHP et Perl est que certaines variables commencent par $, ça n'a pas du tout le même sens d'un langage à l'autre: en PHP ça veut dire que c'est une variable (ou une expression évaluant sur un nom de variable), en Perl ça veut dire que c'est un nom à évaluer dans un contexte scalaire.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-09-2011 à 12:10:52    

Je pense que je vais me tourner vers du python.
Pourquoi pas dans une base de donnée SQL?  
enfin je sens que je vais me tirer les cheveux :)
 
Merci encore l je vous tiens au courant de mon avancé.

Reply

Marsh Posté le 02-09-2011 à 12:14:36    

CPSeb a écrit :

Je pense que je vais me tourner vers du python.
Pourquoi pas dans une base de donnée SQL?


Pourquoi pas quoi dans une base de données SQL?


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-09-2011 à 12:58:47    

Importer mon texte dedans et le retravailler avec des requete SQL ?
C'est mon DSI qui m'avait évoqué un truc du genre mais il ne sait pas comment faire. ( Et de toute facon je n'y connais rien en SQL).
 
Ca va me prendre un certain temps ,je pense, pour arriver a mes fins et créer une routine qui puissent traiter ce genre de fichier.
 
J'y arriverai peut etre jamais..Enfin bon je vais essayer.

Reply

Marsh Posté le 02-09-2011 à 13:10:02    

CPSeb a écrit :

Importer mon texte dedans et le retravailler avec des requete SQL ?
C'est mon DSI qui m'avait évoqué un truc du genre mais il ne sait pas comment faire. ( Et de toute facon je n'y connais rien en SQL).
 
Ca va me prendre un certain temps ,je pense, pour arriver a mes fins et créer une routine qui puissent traiter ce genre de fichier.
 
J'y arriverai peut etre jamais..Enfin bon je vais essayer.


La difficulté ici c'est de parser le fichier d'origine, une fois que t'as ça dans une matrice (ou une liste de maps) en interne tu balances les données où tu veux, que ce soit dans un CSV ou dans une db ça ne fait pas une grande différence.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-09-2011 à 13:33:49    

+1 ce qui a été dit ci-dessus. J'ai personnellement une préférence vers PERL pour ce genre de tâche ingrate impliquant du parsing de fichiers, c'est le langage qui sauve la vie en peu de ligne de codes pour ce genre de choses.
Néanmoins, je me pose la question suivante : ton ticket compta, là, il sort de quoi ? Parce que ça peut être plus intéressant/intelligent de piocher les données à la source si celle-ci est plus facilement accessible, surtout s'il s'agit d'une application qui sort ces données à partir d'un SGBD.

Message cité 2 fois
Message édité par Elmoricq le 02-09-2011 à 13:34:38
Reply

Marsh Posté le 02-09-2011 à 13:33:49   

Reply

Marsh Posté le 02-09-2011 à 13:44:20    

Elmoricq a écrit :

+1 ce qui a été dit ci-dessus. J'ai personnellement une préférence vers PERL pour ce genre de tâche ingrate impliquant du parsing de fichiers, c'est le langage qui sauve la vie en peu de ligne de codes pour ce genre de choses.
Néanmoins, je me pose la question suivante : ton ticket compta, là, il sort de quoi ? Parce que ça peut être plus intéressant/intelligent de piocher les données à la source si celle-ci est plus facilement accessible, surtout s'il s'agit d'une application qui sort ces données à partir d'un SGBD.


Si ça leur vient d'une vieille bécane UNIX, c'est probablement un logiciel semi-mainframe qui date des années 80, truc du style.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-09-2011 à 14:15:27    

Elmoricq a écrit :

+1 ce qui a été dit ci-dessus. J'ai personnellement une préférence vers PERL pour ce genre de tâche ingrate impliquant du parsing de fichiers, c'est le langage qui sauve la vie en peu de ligne de codes pour ce genre de choses.
Néanmoins, je me pose la question suivante : ton ticket compta, là, il sort de quoi ? Parce que ça peut être plus intéressant/intelligent de piocher les données à la source si celle-ci est plus facilement accessible, surtout s'il s'agit d'une application qui sort ces données à partir d'un SGBD.

C'est clair que Perl est particulièrement bien adapté pour faire ce genre de traitement (perso, ça me prendrait moins d'une heure pour pondre le script kivabien en Perl et le tester).  
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 02-09-2011 à 15:40:10    

Merci gilou, pour moi ca va me prendre une année :)
Je comprend pas la moitié de vos propos : parser, SGBD et oui je viens pas de ce monde. ( Enfin si le monde de l'informatique mais c'est tellement vaste..)
 
Pour la machine Unix c'est exactement le cas ( vieille machine des années 80 c'est costaud ces petites bêtes la ).

Message cité 2 fois
Message édité par CPSeb le 02-09-2011 à 15:47:32
Reply

Marsh Posté le 02-09-2011 à 16:50:49    


Transformer un gros tas de texte en des données structurées.


Système de Gestion de Base de Donnée. Ce que t'as en face de toi quand tu fais du SQL (Oracle est un SGBD, Ingres aussi, de même pour Posrgres ou Firebird). L'acronyme anglais est DBMS.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-09-2011 à 20:54:59    

Si le fichier provient d'Unix, il faudrait le traiter avant de le rapatrier. Et là, du awk me semble tout à fait adapté :)


---------------
Doucement le matin, pas trop vite le soir.
Reply

Marsh Posté le 02-09-2011 à 21:08:15    

CPSeb a écrit :

Merci gilou, pour moi ca va me prendre une année :)
Je comprend pas la moitié de vos propos : parser, SGBD et oui je viens pas de ce monde. ( Enfin si le monde de l'informatique mais c'est tellement vaste..)
 
Pour la machine Unix c'est exactement le cas ( vieille machine des années 80 c'est costaud ces petites bêtes la ).

Parser, ça veut dire analyser le contenu d'un fichier ligne a ligne (et effectuer des actions en fonction de ce qu'on trouve à chaque ligne)
SGBD système de gestion de Base de données: vu tes fichiers à parser, on dirait la sortie d'une BDD, et certains ici se demandent si ça serait pas plus efficace de pécher directement les infos à la source.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 02-09-2011 à 21:32:09    

mrbebert a écrit :

il faudrait le traiter avant de le rapatrier.


Does not follow.

mrbebert a écrit :

Et là, du awk me semble tout à fait adapté :)


Et maintenant il doit se taper à la fois awk et un vrai langage pour pouvoir faire tout le boulot?


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-09-2011 à 22:36:41    

Bon, allez, hop, une ébauche de programme en perl, qui marche sur les quelques données qu'il a fourni (après, faudrait en savoir plus sur le format exact des lignes de données). Ca lui permettra d'affiner selon ses besoins. Et il va devoir se plonger un peu dans la notion d'expression régulière pour comprendre le parsing d'une ligne de données comme fait ici.

Code :
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5. my ($numero, $date1, $date2);
  6. my $filename = 'compta.dat'; # fichier des données
  7. open(my $fh, '<', $filename) or die "$filename: fichier pas trouve!"; # ouverture en lecture
  8. # on a pu ouvrir. On ecrit la ligne d'en tête
  9. print "N°       N° écriture  Date/écriture    Nature    Libellé     Code journal    N° de facture    Date/d'échéance    Débit    Crédit \n";
  10. while (<$fh> ) {  # boucle ou on lit une ligne a la fois
  11.  if (/^(\d{6})\s+.*/) { # on a une ligne commençant par un numero à 6 chiffres => on a le numero
  12.    $numero = 0+$1;
  13.  }
  14.  elsif (/^!(\d+)!(\d+\s+\d+\s+\d+)\s+(\S+)\s+(\S+)\s+\*\s+(\d+)\s+\S+\s+(\d+\s+\d+\s+\d+)\s+\*\s*([^!]+)!\s*([^!]+)!/) {
  15.    # on a une ligne de données, commençant par ! suivi de chiffres suivi de ! etc
  16.    if (defined($numero)) { # si on a trouvé un numero avant
  17.      $date1 = todate($2);
  18.      $date2 = todate($6);
  19.      # on imprime ce qu'on a trouvé en le reformatant à sa convenance
  20.      print $numero, "\t", 0+$1, "\t", $date1, "\t", $3, "\t", $4, "\t", 0+$5, "\t", $date2, "\t", $7, "\t", $8, "\n";
  21.    }
  22.    else {
  23.      # print "ERREUR: pas de numero trouve avant les lignes de donnees\n";
  24.    }
  25.  }
  26.  elsif (/^----/) { # ligne avec des -------
  27.    undef $numero; # on efface le numero courant
  28.  }
  29. } # on reboucle et on va traiter la ligne suivante
  30. # fin de la lecture des lignes
  31. close($fh); # on ferme le fichier de données
  32.  
  33. sub todate {
  34.  $_ = shift;
  35.  my $date = "00/00/00";
  36.  if (/(\d+)\s+(\d+)\s+(\d+)/) {
  37.    if ($3 < 12)  {  # remplacer le 12 par l'année ad-hoc s'il y a des échéances pour 2012 ou plus
  38.      $date = $1.'/'.$2.'/'.'20'.$3;
  39.    }
  40.    else {
  41.      $date = $1.'/'.$2.'/'.'19'.$3;
  42.    }
  43.  }
  44.  return $date;
  45. }


todate est une routine qui formate les données pour les dates, en supposant qu'il y a des dates avant 2000 sinon, on peut simplifier.
A+,


Message édité par gilou le 03-09-2011 à 10:26:30

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 02-09-2011 à 23:34:04    

Sans le format exact d'une ligne de données:
!055111!11 10 10  FA    FACTURE           *       055111       ECHEANCE 31 12 10    *         188.13!               !  !  
(par exemple, LIBELLE ECRITURE est il composé de un seul mot, ou peut il y en avoir plusieurs, dans mon code, on suppose qu'il n'y a qu'un mot), il est difficile de pondre une expression régulière dont on soit sur qu'elle colle au format des données.
Celle qui allait sur les données exemples:
^!(\d+)!(\d+\s+\d+\s+\d+)\s+(\S+)\s+(\S+)\s+\*\s+(\d+)\s+\S+\s+(\d+\s+\d+\s+\d+)\s+\*\s*([^!]+)!\s*([^!]+)!
Découpons ça:
Début de ligne: ! suivi des chiffres du numero d'écriture suivi de ! => ^!(\d+)!
^ représente le début de ligne, \d un chiffre, \d+ un ou plusieurs chiffres successifs, et ! le caractère ! final. La parenthèse (\d+) indique qu'on regroupe les chiffres trouvés dans une variable, qui sera $1 (la seconde utilisée pour ranger sera $2, etc jusqu'à $9)
 
Une date formée de chiffres JMA séparés par des blancs, séparée du champ suivant par des blancs => (\d+\s+\d+\s+\d+)\s+
\s est un blanc (caractère espace, tab, etc), \s+ est une succession de blancs. Je regroupe tout ça tout ca sauf les blancs de la fin: (\d+\s+\d+\s+\d+) et ce qui est trouvé pour ce groupe sera rangé dans une variable, ici $2 car c'est le 2e groupe
 
Un mot séparée du champ suivant par des blancs => (\S+)\s+   (\w est peut être plus adapté que \S+, a voir selon les données)
\S est le contraire de \s: un caractère qui n'est pas blanc. \w est une suite de caractères chiffres ou lettres (w est pour word = mot ici)
 
Un mot séparée du champ suivant des blancs => (\S+)\s+ (s'il y a plus qu'un mot possible, ce sera à modifier. si les blancs sont optionnels a la fin, utiliser \s*) => (\S+)\s+
\s+ c'est un ou plusieurs blancs, et \s* c'est 0 ou plusieurs blancs. Selon que les blancs sont obligatoires ou non, on choisira l'un ou l'autre
 
Une étoile suivi de blancs => \*\s+ (si les blancs sont optionnels a la fin, utiliser \s*)
* a un sens spécial, comme on a vu pour \s* avant. Pour le caractère, il faut faire \*  
 
Les chiffres d'un numéro séparés du champ suivant par des blancs => (\d+)\s+
 
Un mot suivi de blancs => \S+\s+  (\w est peut être plus adapté que \S+, a voir selon les données)
 
Une date formée de chiffres JMA séparés par des blancs, séparée du champ suivant par des blancs => (\d+\s+\d+\s+\d+)\s+  (ou \s* si les blancs avant l'étoile sont optionnels)
Comme précédemment pour l'autre date.
 
Une étoile suivi optionnellement de blancs => \*\s*
 
Des caractères quelconques sauf !, et un ! final comme séparateur => ([^!]+)!
La c'est un peu plus dur: [abckz] c'est un des caractères a ou b ou c ou k ou z. [^abckz] c'est le contraire: tout caractère sauf a ou b ou c ou k ou z.
Donc [!] c'est le caractère !, et [^!] c'est tout caractères sauf !. [^!]+ c'est une suite de caractères tous différents de !
Note: on a aussi l'utilisation [a..k] un caractère entre a et k. Un chiffre pourrait se représenter par [0..9], mais on préfère utiliser \d, qui est plus simple.
 
Éventuellement du blanc, suivi de caractères quelconques sauf !, et un ! final comme séparateur =>\s*([^!]+)!
 
 
A+,


Message édité par gilou le 03-09-2011 à 10:23:24

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 05-09-2011 à 12:22:11    

Merci Gilou c'est vraiment sympa de te pencher sur mon problème.
Tes explications sont très détaillées et vont me faire gagner un temps précieux.
Merci d'avoir passer du temps sur mon problème. je te tiens au courant de l'avancer.

Reply

Marsh Posté le 05-09-2011 à 13:02:34    

Alors j'ai executer sous windows ( avec strawberry ) ton script (j'ai juste changer le nom de fichier pour voir) de cette facon  
Dans une fenetre de commande dos je fais :
>perl tonscript.pl
 
De la je vois défilé le résultat (qui m'as l'air d'etre parfait soit dit en passant) mais mon fichier n'est pas re-sauvegarder il faudrait juste réinjecter le résultat obtenu dans un fichier ( .dat ou .csv peu importe )
Je cherche de mon côté sur google ( on sait jamais des fois que je trouve avant que tu répondes )  
 
En tout cas ton explication sur le traitement des chaine de caractères dans un fichiers est vraiment un très bon tutoriel et permet de comprendre rapidement comment arriver a ses fins. C'est vraiment sympa d'avoir expliquer le pourquoi, t'aurai pu te contenter de balancer le script sans l'expliquer (ce qui est déjà énorme) mais la avec l'explication ... vraiment bravo.  Cela va me permettre de le retravaillé (si besoin )


Message édité par CPSeb le 06-09-2011 à 14:00:35
Reply

Marsh Posté le 05-09-2011 à 13:04:40    

j'ai trouvé ( vive dos :) et vive Perl  )  
perl tonscript.pl > fichier.txt


Message édité par CPSeb le 05-09-2011 à 13:04:59
Reply

Marsh Posté le 05-09-2011 à 13:42:01    

J'ai essayé de laisser le script le plus simple possible, pour que tu puisses le modifier en fonction de tes besoins. diriger le tout vers un fichier de sortie, c'est quelques lignes à ajouter, mais ce n'était pas essentiel au fonctionnement.
Ce code saute les lignes qu'il ne sait pas traiter. A toi de vérifier qu'il n'a pas sauté des lignes qu'il n'aurait pas du.
A+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 06-09-2011 à 13:13:06    

Alors j'ai regardé un peu ce qu'il me manque est en faite certaine ligne ne sont pas traité car en effet on selectionne les lignes en fonction du commencement ( si elle commence par !une_suite_de_chiffre! )
En faite je me suis apercu que j'ai quelques lignes qu'il faut que je traite qui commence par !unsymbole_ou_une_lettre_suivi_de_une_suite_de_chiffre!
 
exemple : j'ai des ligne qui commence par !$56999!
 
le mieux serait de dire (au debut) tout ce qui commence par ! ou il n'y a pas de blanc jusqu'au prochain !
 
est ce que c'est : (/^[!][^]+[!])  a la place de  (/^(\d{6})
?


Message édité par CPSeb le 06-09-2011 à 14:04:13
Reply

Marsh Posté le 06-09-2011 à 14:08:15    

mince j'ai ce message d'erreur ( qui se repete line 95 , line 97 line 10 etc..)
use of uninitialized value $1 in addition (+) at test2.pl line 10, <$fh> line 31
 
( qui se repete line 95 , line 97 line 10 etc..)

Reply

Marsh Posté le 06-09-2011 à 14:30:12    

Citation :

exemple : j'ai des ligne qui commence par !$56999!


Pour matcher, tu vas pouvoir faire:
\D(\d{5}) ou  (\D\d{5})
selon que tu veux que les chiffres ou les chiffres avec la lettre devant.
 
Mais ça va compliquer le traitement. Tu as des numéros d'écriture qui sont pas des numéros qu'avec des chiffres?
C'est une ligne de quel type?
Comme
000008   Risque aut.    45KF  *  
Ou comme
!055117!11 10 10  FA    FACTURE           *       055117       ECHEANCE 31 12 10    *       1 272.63!               !  !  
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 06-09-2011 à 14:52:46    

Voici un exemplede ligne qui ne fonctionne pas:
 
!$69172!19 03 10  03    ECH 100310 IMPAYE * 5124   OPERATION DIVERSE                *       2 026.17!               !  !
!$69218!29 03 10  03    IMPAYE 100210     * 5124   OPERATION DIVERSE                *       2 026.00!               !  !
!      !2 CHQ PTF EN REGLT IMPAYES 10/03/10 ET 10/02/10 - MR PALA DEMANDE UN        *               !               !  !
!      !DELAI POUR QUE NOUS LES REMETTIONS CAR DIFFICULTES DE TRESORERIE            *               !               !  !
!$69535!07 05 10  03    IMPAYE 30/04/10   * 5124   OPERATION DIVERSE                *       1 196.72!               !  !
!*31720!26 05 10  CC    CHEQUE            * 5124   CHEQUE RECU                      *               !       1 350.17!  !
 
il faut traiter dans cette exemple les 2 premières et les deux dernières
 
Toutes les lignes que je veux traiter commencent toujours par ! il y a des caractères sans aucun espace et finissent par !
il faudrait prendre ceux qui est contenu entre les deux ! ( j'ai vu que t'as crées une variable $nombre et donc ca ne marchera pas si il y a les symboles).
 
A+  


Message édité par CPSeb le 06-09-2011 à 14:54:26
Reply

Marsh Posté le 06-09-2011 à 16:04:13    

Oui, mais la, la structure de ta ligne est différente:
!$69535!07 05 10  03    IMPAYE 30/04/10   * 5124   OPERATION DIVERSE                *       1 196.72!               !  !  
Par exemple, il y a pas de date d'échéance.
Ça doit alimenter ta feuille excel comment une telle ligne?
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 08-09-2011 à 10:07:53    

Bon après analyse attentive et après discussion avec mon DSI voici ce qu il serait bien dans un premier temps ( ca va etre plus compliqué je pense)
Chaque ecriture est liée à un numero de compte qui est donnée apres une ligne d'asterisque, ce numéro de compte est toujour composé de 6 chiffres (sans espace devant)
ensuite vient les ecritures ou il faut "juste" dans un premier temps recupérer les ligne qui commencent par un ! suivi de 6 caractère SANS BLANC suivi d'un autre !  
Il nous faut donc récuperer ce numéro de compte, le mettre dans une colonne a gauche par exemple suivi des lignes d'écritures (on supprimera juste les asteriques et le point d'exclamation qui sont de trop.
Exemple :
 
**************************************************************************        
001778  SOCIETE 75002 Teleph: 02.02.02.02.02 Risque aut.    50KF  *        
  EFFET 60 J FM        
************************************************************************************************************************        
! ECR. !  DATE  ! NAT ! LIBELLE ECRITURE  *  JAL  ! PIECE  D'ORIGINE                *    DEBIT      !   CREDIT      !LT!        
************************************************************************************************************************        
!054680!27 09 10  FA    FACTURE           *       054680       ECHEANCE 31 12 10    *         209.30!               !  !        
!054747!29 09 10  FA    FACTURE           *       054747       ECHEANCE 31 12 10    *         305.10!               !  !        
!054755!29 09 10  FA    FACTURE           *       054755       ECHEANCE 30 11 10    *         270.83!               !  !        
!054907!04 10 10  FA    FACTURE           *       054907       ECHEANCE 31 12 10    *       1 470.36!               !  !        
!054911!04 10 10  FA    FACTURE           *       054911       ECHEANCE 31 12 10    *      55 447.16!               !  !        
!054970!05 10 10  FA    FACTURE           *       054970       ECHEANCE 31 12 10    *          95.68!               !  !        
!054972!05 10 10  FA    FACTURE           *       054972       ECHEANCE 31 12 10    *       4 471.37!               !  !        
!055003!06 10 10  FA    FACTURE           *       055003       ECHEANCE 31 12 10    *       3 927.81!               !  !        
!055043!07 10 10  AV    AVOIR             *       055043       ECHEANCE 31 12 10    *               !         592.67!  !        
!055044!07 10 10  FA    FACTURE           *       055044       ECHEANCE 31 12 10    *         604.65!               !  !        
!055046!07 10 10  FA    FACTURE           *       055046       ECHEANCE 31 12 10    *       2 883.44!               !  !        
!055082!08 10 10  AV    AVOIR             *       055082       ECHEANCE 31 12 10    *               !         509.24!  !        
!055089!08 10 10  FA    FACTURE           *       055089       ECHEANCE 31 01 11    *       3 408.60!               !  !        
!055090!08 10 10  FA    FACTURE           *       055090       ECHEANCE 31 01 11    *         872.91!               !  !        
!$70611!11 10 10  03    DED. S/FAC 51697  * 8000   OPERATION DIVERSE                *          49.01!               !  !        
!$70614!11 10 10  03    DED. S/FAC 51697  * 8000   OPERATION DIVERSE                *       1 029.25!               !  !        
!$70616!11 10 10  03    DED. S/FAC 51959  * 8000   OPERATION DIVERSE                *         430.72!               !  !        
!$70618!11 10 10  03    DED. S/FAC 51560  * 8000   OPERATION DIVERSE                *         163.45!               !  !        
!$70620!11 10 10  03    DED. S/FAC 51706  * 8000   OPERATION DIVERSE                *         109.42!               !  !        
!$70622!11 10 10  03    DED. S/FAC 49903  * 8000   OPERATION DIVERSE                *         501.20!               !  !        
!$70624!11 10 10  03    DED. S/FAC 49903  * 8000   OPERATION DIVERSE                *         396.56!               !  !        
!$70626!11 10 10  03    DED. S/FAC 49905  * 8000   OPERATION DIVERSE                *         833.28!               !  !        
!$70630!11 10 10  03    DED. S/FAC 50330  * 8000   OPERATION DIVERSE                *       1 464.30!               !  !        
!$70632!11 10 10  03    DED. S/FAC 50331  * 8000   OPERATION DIVERSE                *         755.35!               !  !        
!055145!12 10 10  FA    FACTURE           *       055145       ECHEANCE 31 12 10    *         857.28!               !  !        
!055146!12 10 10  FA    FACTURE           *       055146       ECHEANCE 31 12 10    *         840.38!               !  !        
!055147!12 10 10  FA    FACTURE           *       055147       ECHEANCE 31 12 10    *       1 837.34!               !  !        
!055218!13 10 10  FA    FACTURE           *       055218       ECHEANCE 31 01 11    *         404.83!               !  !        
!055252!14 10 10  FA    FACTURE           *       055252       ECHEANCE 31 01 11    *       2 882.81!               !  !        
!055257!14 10 10  FA    FACTURE           *       055257       ECHEANCE 31 12 10    *       3 950.29!               !  !        
!055258!14 10 10  FA    FACTURE           *       055258       ECHEANCE 31 01 11    *       3 051.81!               !  !        
!055274!15 10 10  FA    FACTURE           *       055274       ECHEANCE 31 01 11    *       1 173.78!               !  !        
!055289!18 10 10  AV    AVOIR             *       055289       ECHEANCE 31 12 10    *               !         110.96!  !        
!055294!18 10 10  FA    FACTURE           *       055294       ECHEANCE 31 12 10    *         108.57!               !  !        
!055480!20 10 10  FA    FACTURE           *       055480       ECHEANCE 31 12 10    *       1 126.87!               !  !        
!055481!20 10 10  AV    AVOIR             *       055481       ECHEANCE 31 12 10    *               !         484.38!  !        
!055536!22 10 10  FA    FACTURE           *       055536       ECHEANCE 31 01 11    *       1 009.13!               !  !        
!055537!22 10 10  FA    FACTURE           *       055537       ECHEANCE 31 12 10    *       3 875.52!               !  !        
!055538!22 10 10  FA    FACTURE           *       055538       ECHEANCE 31 12 10    *       2 232.32!               !  !        
!055612!25 10 10  AV    AVOIR             *       055612       ECHEANCE 31 12 10    *               !       1 921.88!  !        
!$70736!26 10 10  03    RECU S/FAC 51697  * 8000   OPERATION DIVERSE                *               !         147.04!  !        
!055623!26 10 10  FA    FACTURE           *       055623       ECHEANCE 31 12 10    *       2 632.48!               !  !        
!055624!26 10 10  FA    FACTURE           *       055624       ECHEANCE 31 01 11    *       2 319.55!               !  !        
!055625!26 10 10  FA    FACTURE           *       055625       ECHEANCE 31 01 11    *       2 542.12!               !  !        
!055651!26 10 10  FA    FACTURE           *       055651       ECHEANCE 31 12 10    *       2 010.79!               !  !        
!055662!26 10 10  FA    FACTURE           *       055662       ECHEANCE 31 12 10    *       2 014.51!               !  !        
!055663!26 10 10  FA    FACTURE           *       055663       ECHEANCE 31 12 10    *       1 673.73!               !  !        
 
Après traitement ( le résultat final voulu ) :  
 
N° de compte N° écriture Date/écriture Nature Libellé                        Code journal N° de facture Date/d'échéance Débit Crédit
001778               54680               27/09/2010 FA FACTURE                                            54680               31/12/2010 209.30  
001778               54747               29/09/2010 FA FACTURE                                            54747               31/12/2010 305.1
001778               54755               29/09/2010 FA FACTURE                                            54755               30/11/2010 270.83  
001778               54907               04/10/2010 FA FACTURE                                            54907               31/12/2010 1470.36  
001778               54911               04/10/2010 FA FACTURE                                            54911               31/12/2010 55447.16  
001778               etc...               etc...               etc... etc...                                                         etc...               etc...  etc...  
001778               70611               11/10/2010 03 DED. S/FAC 51697          8000        OPERATION DIVERSE               49.01  
025556                 22222                  22/22/2222          FA          FACTURE                                                        22222                  22/22/2222         2222.22
 
j'ai mis une ligne factice en dessous pour simuler une autre ecriture sur un autre compte (histoire que tu comprennes mieux car c'est pas forcément évident)
 
Dans un premier temps si on peut juste copier le numéro de compte  suivi des lignes d'écritures tel quel ( sauf peut etre juste enlever les * et les ! )
 
Donc dans la méthode se serait en gros:  
Des qu'on rencontre un numéro a 6 chiifres on ne garde que lui sur cette ligne
ensuite des qu'on rencontre une ligne qui commence par ! avec 6caractère sans espace et ! on remet le numero de compte devant suivi de la ligne sans les ! et *
 
Je sais pas si c'est très clair...


Message édité par CPSeb le 08-09-2011 à 10:09:19
Reply

Marsh Posté le 08-09-2011 à 12:51:57    

si j'ai compris ton explication  
si je fais  
^!(\w)!  cela va prendre toute les ecritures qui commence par ! suivi d'une chaine de caractère sans blanc et qui fini par !
j'ai bon ?
 
apres y'as t'il un moyen de prendre tout ce qui suit dans la ligne en remplacant les ! et les * par un blanc ( je pense que ce serait le plus simple..)

Message cité 1 fois
Message édité par CPSeb le 08-09-2011 à 12:52:25
Reply

Marsh Posté le 08-09-2011 à 14:37:35    

Bon je pense qu'en t'inspirant de ceci, tu devrais pouvoir adapter pour ton résultat final:

Code :
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. my $filename = 'compta.dat'; # fichier des données
  7. open(my $fh, '<', $filename) or die "$filename: fichier pas trouve!"; # ouverture en lecture
  8.  
  9. my $linenum = 0;
  10. my $numero;
  11. my $parsedline;
  12. $parsedline = makeheaderline();
  13. writeline($parsedline);
  14. while (<$fh> ) {
  15.  ++$linenum;
  16.  if (/^(\d{6})\s+.*/) { # si ligne débutant par un nombre à 6 chiffres
  17.    $numero = 0+$1;
  18.    # 0+$1 pour interpréter la valeur comme un nombre,
  19.    # $1 seul l'interpréterait comme du texte et garderait le(s) 0 du début
  20.  }
  21.  if (/^![^!\s]+!/) {
  22.    if (/^!([^!\s]+)!(\d+\s+\d+\s+\d+)\s+(\S+)\s+([^*]+)\*([^*]+)\*([^!]+)!([^!]+)![^!]+!\s*$/) {
  23.      if (defined($numero)) {
  24.     $parsedline->{'numero'}  = $numero;
  25.     $parsedline->{'ecr'}     = formatnum($1);
  26.     $parsedline->{'date'}    = formatdate($2);
  27.     $parsedline->{'nat'}     = $3;
  28.     $parsedline->{'libelle'} = trim($4);
  29.     $parsedline->{'jal'}     = ""; # On va traiter ces champs après
  30.     $parsedline->{'facture'} = "";
  31.     $parsedline->{'echance'} = "";
  32.     $parsedline->{'debit'}   = trim($6);
  33.     $parsedline->{'credit'}  = trim($7);
  34.  
  35.     $_ = trim($5); # c'est sur la valeur de $5 qu'on va maintenant chercher des patterns
  36.     if (/^(\d+)\s+ECHEANCE\s+(\d+\s+\d+\s+\d+)/) { # on repere une echance
  37.       $parsedline->{'facture'} = formatnum($1);
  38.       $parsedline->{'echance'} = formatdate($2);
  39.     }
  40.     elsif (/^(\d+)\s+(.*)$/) { # sinon, si on a un numero, ce doit être un numero de journal (?)
  41.       $parsedline->{'jal'} = formatnum($1);
  42.       $parsedline->{'facture'} = trim($2); # Si c'est la qu'on range les choses comme OPERATION DIVERSES
  43.     }
  44.     else { # pas de numero journal repere, on flanque le tout dans facture (ou ailleurs?, ou cas d'erreur?)
  45.       $parsedline->{'facture'} = $_;
  46.     }
  47.  
  48.     writeline($parsedline);
  49.     undef($parsedline);
  50.      }
  51.      else {
  52.     print "ERREUR: $0 ligne $linenum pas de numero trouve avant les lignes de donnees\n";
  53.      }
  54.    }
  55.    else {
  56.      print "ERREUR: $0 ligne $linenum pas au format attendu\n";
  57.    }
  58.  }
  59.  elsif (/^-+\s*$/) { # -+ signifie un ou des - successifs
  60.    undef $numero;
  61.  }
  62. }
  63. close($fh);
  64.  
  65. sub makeheaderline {
  66.  my $line;
  67.  $line->{'numero'}  = "N° de compte";
  68.  $line->{'ecr'}     = "N° écriture";
  69.  $line->{'date'}    = "Date/écriture";
  70.  $line->{'nat'}     = "Nature";
  71.  $line->{'libelle'} = "Libellé";
  72.  $line->{'jal'}     = "Code journal";
  73.  $line->{'facture'} = "N° de facture";
  74.  $line->{'echance'} = "Date/d'échéance";
  75.  $line->{'debit'}   = "Débit";
  76.  $line->{'credit'}  = "Crédit";
  77.  return $line;
  78. }
  79.  
  80. sub writeline {
  81.  my $line = shift;
  82.  print $line->{'numero'},  "\t",
  83.        $line->{'ecr'},     "\t",
  84.     $line->{'date'},    "\t",
  85.     $line->{'nat'},     "\t",
  86.     $line->{'libelle'}, "\t",
  87.     $line->{'jal'},     "\t",
  88.     $line->{'facture'}, "\t",
  89.     $line->{'echance'}, "\t",
  90.     $line->{'debit'},   "\t",
  91.     $line->{'credit'},  "\n";
  92. }
  93.  
  94. sub formatdate {
  95.  use constant DATESPLIT => 25; # 00..25 -> 2000..2025 et t26..99 -> 1926..1999
  96.  $_ = shift;
  97.  my $date = "00/00/00";
  98.  if (/(\d+)\s+(\d+)\s+(\d+)/) {
  99.    if ($3 > DATESPLIT)  {
  100.      $date = $1.'/'.$2.'/'.'19'.$3;
  101.    }
  102.    else {
  103.      $date = $1.'/'.$2.'/'.'20'.$3;
  104.    }
  105.  }
  106.  return $date;
  107. }
  108.  
  109. sub formatnum { # enlève les zéros ou les lettres autres que des chiffres au début
  110.  $_ = shift;
  111.  s/^(0|\D)+//;
  112.  return $_;
  113. }
  114.  
  115. sub trim { # enlève les blancs à droite et à gauche
  116.  $_ = shift;
  117.  s/^\s+//;
  118.  s/\s+$//;
  119.  return $_;
  120. }


 
A+,


Message édité par gilou le 08-09-2011 à 14:56:50

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 08-09-2011 à 14:51:52    

Le découpage est plus grossier:
/^!([^!\s]+)!(\d+\s+\d+\s+\d+)\s+(\S+)\s+([^*]+)\*([^*]+)\*([^!]+)!([^!]+)![^!]+!\s*$/
^début de ligne
!([^!\s]+)! un premier champ ne contenant pas de blancs, entre deux ! (N° écriture)
(\d+\s+\d+\s+\d+)\s+  une date délimitée par du blanc final (Date/écriture)
(\S+)\s+  du texte sans blanc ( donc un mot, \w convient aussi sans doute) délimitée par du blanc final (Nature)
([^*]+)\* du texte délimité par un * final (Libellé)
([^*]+)\* du texte délimité par un * final (Code journal et N° de facture et Date/d'échéance)  
([^!]+)! du texte délimité par un ! final (Débit)
([^!]+)! du texte délimité par un ! final (Crédit)
[^!]+! du texte délimité par un ! final  (LT dans le fichier original. on ne stocke pas la valeur)
\s*$ éventuellement du blanc, puis la fin de ligne.
 
Donc a part un peu de formatage pour les champs, c'est celui qui contient Code journal et N° de facture et Date/d'échéance qui est à découper avec un peu plus de précision. A toi d'adapter ce que j'ai fait dans le code précédent si ça ne te convient pas.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 08-09-2011 à 14:54:55    

CPSeb a écrit :

si j'ai compris ton explication  
si je fais  
^!(\w)!  cela va prendre toute les ecritures qui commence par ! suivi d'une chaine de caractère sans blanc et qui fini par !
j'ai bon ?

Oui, mais si c'est en début de ligne (ça commence par ^)  
 

CPSeb a écrit :

apres y'as t'il un moyen de prendre tout ce qui suit dans la ligne en remplacant les ! et les * par un blanc ( je pense que ce serait le plus simple..)

J'ai pas compris ce que tu veux, la.
 
A+,


Message édité par gilou le 08-09-2011 à 14:55:59

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 08-09-2011 à 17:14:41    

Gilou t'es trop fort !
J'ai toutes mes lignes d'écriture avec le numéro de compte, c'est génial.
Juste une petite retouche a faire au niveau de certaine ligne ou le mot echeance apparait encore et la date n'est pas au bonne endroit...
Je regarde pus en detail demain.  
A+ à demain.

Reply

Marsh Posté le 08-09-2011 à 17:38:14    

Content que tu aie trouvé ! ;)
 
Par contre, y'en a marre  de lire des gros trolls poilus sur le php :

masklinn a écrit :


Non. Perl a une très grande librairie tierce (CPAN), des fonctions natives très orthogonales, une syntaxe littérale pour les regex et un excellent support pour tout ce qui est manipulation de chaînes.
 
PHP est un grand sac de merde.


 
php est capable du pire comme du meilleur
 
Désolé d'avoir nourri le troll, j'ai juste pas pu résister :D
 [:oinseach]

Reply

Marsh Posté le 08-09-2011 à 17:43:40    

mdc888 a écrit :

php est capable du pire comme du meilleur


Non, PHP n'est capable que du pire, les gens sont capables du meilleur en dépit de PHP, pas grâce à lui [:skeye]

 

Et ça n'a rien d''un troll, c'est une description parfaitement objective.

Message cité 1 fois
Message édité par masklinn le 08-09-2011 à 17:45:11

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 08-09-2011 à 17:58:57    

masklinn a écrit :


Non, PHP n'est capable que du pire, les gens sont capables du meilleur en dépit de PHP, pas grâce à lui [:skeye]  
 
Et ça n'a rien d''un troll, c'est une description parfaitement objective.


 
Aller, cette fois je m'y tiens ;)
 [:oinseach]

Reply

Marsh Posté le 08-09-2011 à 19:33:14    

Perso, je pense que Masklinn est assez objectif.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 08-09-2011 à 20:29:13    

Vrai ?
Bon, bah mes excuses alors... ;)
Mais je reste persuadé que ca peut être un bon langage lorsqu'il est bien maitrisé

Reply

Marsh Posté le 08-09-2011 à 21:36:27    

On en a vu dire la même chose au sujet du Cobol ou de Windev... :whistle:  
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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