Bonjour à tous,

voilà mon petit souci. J'ai un fichier comportant sur chaque ligne un certain nombre de champs se suivant séparés par un espace et définis ainsi :
<NOM_CHAMP>:<VALEUR>
Je ne connais pas à l'avance les noms des champs, ni leur nombre. Les valeurs peuvent prendre à peu près n'importe quelle forme (alphanumérique, quelques symboles y compris espace et deux-points...).

Mon but est, vous l'aurez compris, de recréer un tableau plus classique à partir de ce fichier (au format type csv par exemple).

On peut prendre les règles suivantes quand même (pour simplifier un peu - voir script) :
1. pas de point-virgule ou de guillemets ou de caractères trop "chiants" =)
2. un nom de champ commence par une lettre et ne contient que des caractères alphanumériques ou underscore
3. conclusion de 1 & 2 : je repère chaque champ en trouvant un espace suivi d'une lettre éventuellement plusieurs caractères alphanumériques ou underscore et deux-points

J'ai réussi à faire un script qui fonctionne plutôt bien MAIS qui me pose problème au traitement du dernier champ de la ligne ^^ :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/perl
 
use strict;
 
open (FIC_E, "dsv.txt") or die ("dsv.txt : $!");
open (FIC_S, ">dsv.csv") or die ("dsv.csv : $!");
 
my $result;
my @keys;
my $nbrow=0;
 
while (<FIC_E>) {
	my @matches = m/(?:([a-zA-Z]\w+)\:(?:(.*?)\s?)(?=[a-zA-Z]\w+\:))/g;
 
	next if ($#matches <= 0);
	for (my $i=0; $i <= $#matches+1; $i+=2) {
		push (@{$result->{$matches[$i]}}, $matches[$i+1]);
		push (@keys,$matches[$i]) if ($nbrow == 0);
	}
	if (/([a-zA-Z]\w+)\:$/) {
		push (@{$result->{$1}}, "");
		push (@keys,$1) if ($nbrow == 0);
	}
	$nbrow++;
}
 
foreach my $key (@keys) {
	print FIC_S $key,";";
}
print FIC_S "\n";
for (my $i=0; $i < $nbrow; $i++) {
	foreach my $key (@keys) {
		print FIC_S '"',$result->{$key}->[$i],'";';
	}
	print FIC_S "\n";
}
 
close FIC_E;
close FIC_S;
La partie intéressante ici est bien entendu ma regexp :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
#m/(?:
#	([a-zA-Z]\w+)\: ==> définition d'un nom de champ : une lettre + alphanum ou underscore...
#	(?:(.*?)\s?) ==> capture des valeurs correspondantes : le \s? est là pour virer le dernier espace (oui, un champs peut n'être composé que d'espaces)
#	(?=[a-zA-Z]\w+\:) ==> je m'arrête quand je détecte un nouveau nom de champ
#)/g
Il y a peut-être (sûrement) mieux ? Quoiqu'il en soit, ça marche bien comme je l'ai dit, sauf pour le dernier champ puisqu'il ne trouve pas de nouveau nom de champ à la suite

Exemple
mon entrée:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
VAR:10 ID:0000000001 DATE: 2008-04-19 14:12:55
VAR: 1 ID:           DATE: 2008-04-19 14:13:15
VAR:10 ID:0000000009 DATE: 2008-04-19 14:14:32
ma sortie:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
VAR;ID;
"10";"0000000001";
" 1";"          ";
"10";"0000000009";
ce que je voudrais:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
VAR;ID;DATE;
"10";"0000000001";" 2008-04-19 14:12:55";
" 1";"          ";" 2008-04-19 14:13:15";
"10";"0000000009";" 2008-04-19 14:14:32";
merci =)