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 ^^ :
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
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;
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
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
Exemple
mon entrée:
ma sortie:
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
ce que je voudrais:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 VAR;ID; "10";"0000000001"; " 1";" "; "10";"0000000009";
merci =)
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";
Partager