Concatenation lignes - Perl - Programmation
Marsh Posté le 07-12-2015 à 12:59:31
Faudrait peut être faire l'effort de donner un fichier de test valide.
LET MODERN|LOUVOIS|LOUVOIS|JOSE|21/11/1984|CERT|NANTES|Ancienneté dans le poste|N|
Alors que ça devrait être
LET MODERN|LOUVOIS|LOUVOIS|JOSE|21/11/1984|CERT|NANTES|Ancienneté dans le poste|1|N|
au vu de ta sortie désirée
A+,
Marsh Posté le 07-12-2015 à 13:23:18
gilou a écrit : Faudrait peut être faire l'effort de donner un fichier de test valide. |
Autant pour moi. C'est corrigé.
Marsh Posté le 07-12-2015 à 14:23:04
Code :
|
La ligne est constituée de 10 suites d'un truc formé de texte suivi d'un |. Je colle un tel truc dans une regexp
my $re = qr{(?:[^|]+\|)};
pour réutilisation sous une forme plus lisible. (?:...) est un non-capturing group, qui ne colle pas automatiquement ce qui matche dans une variable.
Bon, on parse ligne a ligne. Si on a une ligne de la forme attendue:
if (/^(?<start>$re{7})(?<mid>$re{2})(?<end>$re)$/) {
(?<nom>...) est un named-capturing group, qui colle ce qui matche dans une variable de nom $+{nom}
Ici, je mets les 7 premiers trucs (éventuellement communs a plusieurs lignes) dans une variable $+{start}, idem pour le truc final, dans $+{end}, et les 2 trucs variables entre les deux seront collés dans $+{mid}.
Si c'est la première ligne
if ($. == 1) {
On imprime le début et le milieu (pas la fin car il y aura peut être d'autres milieux à ajouter)
print $+{start}, $+{mid};
et on stocke le début et la fin courante
($prev_start, $prev_end) = ($+{start}, $+{end});
Sinon, si c'est pas la première ligne
Si le début est le même que celui de la ligne précédente
if ($prev_start eq $+{start}) {
On imprime le nouveau milieu
print $+{mid};
Sinon, si le début est différent de celui de la ligne précédente
On a une nouvelle ligne donc on imprime la fin de la ligne précédente, puis le début et le milieu de la nouvelle ligne en cours
print $prev_end, "\n", $+{start}, $+{mid};
Et on stocke le nouveau début et la nouvelle fin
($prev_start, $prev_end) = ($+{start}, $+{end});
En fin de fichier, on imprime la fin de la dernière ligne lue, s'il y en a une
if ($prev_end) { print $prev_end, "\n"; }
et voila.
Note:
Si on peut avoir des champs vide, et donc un || dans les données, remplacer la regexp
my $re = qr{(?:[^|]+\|)};
par
my $re = qr{(?:[^|]*\|)};
Il y avait aussi moyen de passer par des arrays, ou plutôt par des hashes, mais pour juste cette fusion de lignes, c'était un peu le coup de l'enclume pour craser une mouche. Sinon, une utilisation de Text::CSV aurait pu être pratique.
ou bien faire un
my @fields = qw(discipline nom nom_patro prenom datenaissance grade ville bareme bareme_val yn);
my %data;
...
@data{@fields} = split /\|/;
qui aurait collé les valeurs lues dans le hash suivant l'ordre des clés prises dans @fields.
C'est un idiome perl bien pratique.
A+,
Marsh Posté le 07-12-2015 à 15:47:41
Un GRAND MERCI ! Trop fort ! ça fonctionne très bien
Pour aller plus loin, j'aimerai savoir ce que je dois modifier pour traiter des lignes avec 19 valeurs comme ceci :
Code :
|
Vu que j'ai en effet des valeurs vides, j'ai tenté de modifier comme tu me l'a dis la regex : my $re = qr{(?:[^|]*\|)};
Mais j'ai une erreur en sortie...
Marsh Posté le 07-12-2015 à 15:59:51
my $re = qr{(?:[^|]*\|)};
oui,
et il faut modifier
if (/^(?<start>$re{7})(?<mid>$re{2})(?<end>$re)$/) {
en fonction de ce qui sera commun ou non.
A vue de nez, ce pourrait être
if (/^(?<start>$re{7})(?<mid>$re{2})(?<end>$re{10})$/) {
mais je ne connais pas vos données.
Ici, j'ai supposé que les 10 derniers champs étaient eux aussi communs.
Je suppose que vous n'avez pas des lignes à 10 et 19 champs dans le même fichier.
A+,
Marsh Posté le 07-12-2015 à 16:22:32
C'est ce que j'ai fais aussi pour : if (/^(?<start>$re{7})(?<mid>$re{2})(?<end>$re{10})$/) {
J'ai testé de ça me renvoie le résultat suivant :
Code :
|
il manque :
Code :
|
après "|3|".
Apres la valeur "|O|", les données sont différentes, la valeur entre 2 "|" peut être vide ou pas...
Toujours est-il qu'on aura toujours 19 valeurs entre les "|".
Marsh Posté le 07-12-2015 à 20:04:55
Moi, a partir de vos données, j'ai fait le fichier de test suivant:
ANGLAIS|BOBIN|BOBIN|JEAN|28/10/1966|CERT. CL N|MONTPEL.|Mention Complementaire|Non||O| | | |||||N| |
et le code que je vous ai donné,
Code :
|
il me donne ceci en sortie:
ANGLAIS|BOBIN|BOBIN|JEAN|28/10/1966|CERT. CL N|MONTPEL.|Mention Complementaire|Non|Ancienneté dans le poste|3|Ancienneté de service|8||O| | | |||||N| |
EDIT: Je subodore que votre 3e ligne n'avait pas 19 champs, et donc qu'elle n'a pas été prise en compte.
A+,
Marsh Posté le 07-12-2015 à 11:08:32
Bonjour à tous,
Je débute en perl et je n'arrive pas à concaténer des lignes.
Je m'explique, j'ai 1 seul fichier texte constitué ainsi :
Je cherche à faire un test sur la ligne pour donner le resultat suivant :
Pour l'instant, voici ce que j'ai réussis à faire mais qui ne fonctionne pas:
Après plusieurs tentative de tests, je n'arrive pas à écrire :
Dans le fichier, SI disciplineligne1 & nomligne1 & prenomigne1 = disciplineligne2 & nomligne2 & prenomigne2 ALORS...
Merci d'avance pour votre aide.
Message édité par supermallain le 07-12-2015 à 13:22:46