simplifier ma regex [Perl] - Perl - Programmation
Marsh Posté le 06-12-2015 à 12:51:58
Voila une version plus directe, au vu de tes données:
Code :
|
J'ai choisi |...| pour encadrer la regex plutôt que l'habituel /.../ parce qu'il y a des / dans la chaîne à parser (et que je suppose qu'il n'y aura pas de | dans cette chaîne).
si tu veux que ta regexp soit plus lisible, avec le modifier x, on peut la mettre sur plusieurs lignes:
Code :
|
Mais bon, une manière bien plus logique de procéder est la suivante:
Code :
|
Si on repère une ligne à traiter: if (/Cmd=CreateSession/)
On splitte les champs selon la virgule: my @fields = split /,/;
Ils sont tous de la forme XX=YYY sauf le premier.
On colle le premier champ dans une variable a part: my $time = shift @fields;
On colle les autres dans un hash, un champ de la forme XX=YYY fournissant un élment du hash de clé XX et de valeur YYY: my %hash = map {if (/(.+)=(.+)/) {($1, $2)}} @fields;
On extrait du premier champ de qui nous intéresse: $time =~ s|^(\d\d\d\d)/(\d\d)/(\d\d)\s(\d\d):(\d\d):(\d\d)\.\d+.+|$1$2$3$4$5$6|o;
qu'on envoie en sortie avec les valeurs du hash pour certaines clés: print "$time|$hash{SesId}|$hash{BW}|$hash{GDA}|LOG-01\n";
et c'est tout, zou!
Note:
J'ai écrit
my %hash = map {if (/(.+)=(.+)/) {($1, $2)}} @fields;
ça marche parce que je suis certain que tous les champs sont de la forme XX=YYY
Si je n'en suis pas sur, faire
my %hash;
map {if (/(.+)=(.+)/) {$hash{$1}=$2} @fields;
qui marche à tout les coups et ne tient compte que des champs de la bonne forme XX=YYY et saute ceux qui sont d'une autre forme.
En y repensant, un
my %hash = grep /./, map {if (/(.+)=(.+)/) {($1, $2)}} @fields;
fera la même chose (les champs d'une autre forme, qui renvoient undef avec map sont éliminés par le grep) et est un one liner.
Après, si on veut faire plus compact et moins lisible et maintenable, on peut toujours faire tout avec un hash unique:
Code : |
On peut rendre ça encore plus compact
Code :
|
Et si on veut, quitte a laisser tomber $result et a se placer dans le cadre de ton utilisation réelle (lecture en boucle ligne à ligne d'un log), on peut même aboutir à un one liner, guru-level illisible.
Code :
|
En ce qui me concerne, je ferais ceci:
Code :
|
Parce que c'est lisible, compréhensible (pour qui pratique un peu Perl), et surtout, flexible et réutilisable: le jour ou tu veux imprimer une autre valeur de champ en sortie, par exemple celui associé à MPN, il te suffira de coller $hash{MPN} dans le print.
A+,
Marsh Posté le 06-12-2015 à 19:42:01
Waouh !
Ça c'est de la réponse qui envoie du lourd
Chapeau bas Mr Gilou
C'est très clair et en plus j'apprends des nouvelles choses
Merci
Marsh Posté le 05-12-2015 à 17:42:50
Hello,
Voici ma ligne à parser:
Mon but est d'obtenir ça:
J'y arrive avec ce code ci-dessous
Mais je ne trouve pas ma regex super jolie et je voudrai arriver à récupérer mes variables sans les nettoyer (ce que je fais en ligne 4. et 6. et 7.)
Est-ce qu'il est possible de faire plus simple et plus propre?
Merci d'avance.