[PERL expreg] capture optionnelle ou EOL

Résolu/Fermé
sbouli Messages postés 200 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 14 août 2014 - 26 août 2010 à 12:34
sbouli Messages postés 200 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 14 août 2014 - 26 août 2010 à 15:23
Bonjour,

Je cherche à capturer un élément de manière optionnel :

A1F712492D9B|info_46943_0_11111@domaine.com
C55657BC738|info_48894_0_22222@domaine.com|20100826_121900



aujourd'hui je fais :
while (<FICHIER_HOLD>) {
	(($clef,$valeur) = /([^|]+)\|(.*)$/i);
}

qui me prend bien clef et valeur selon le |, mais je souhaiterais ajouter un élément optionnel correspondant à une date heure (ligne 2 de l'exemple) présente ou non après un |, j'ai bien bricoler un peu mais sans succès :

([^|]+)\|([^|]+)\|([^|]+)


pourtant j'ai bien lu le bouquin sur les expressions régulières ... ça doit pas être sorcier ...

Merci d'avance pour votre aide !

Stéphane
A voir également:

6 réponses

Leviathan49 Messages postés 257 Date d'inscription jeudi 10 juin 2010 Statut Membre Dernière intervention 22 juillet 2011 70
26 août 2010 à 14:05
Après quelques essai je te propose ceci : ([^|]+)\|([^|\s]+)(?:\|([^\s]+))?
Cela devrait marcher si tes champs entre pipe ne contiennent pas d'espaces, sinon ca va être plus compliqué...
1
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 569
Modifié par lami20j le 26/08/2010 à 14:46
Re,

Oups, j'ai fait une erreur. Quand on mets les "" alors split considére qu'il s'agit d'une chaine de caractères. Donc c'est /\|/ et pas "/\|/"

Ensuite il faut juste faire un test pour print comme ça plus des warnings.

~ $ cat champs_underscore.pl
#!/usr/bin/perl  
use strict;use warnings;  

while (<DATA>) {  
  my ($clef,$valeur,$datehold) = split /\|/;  
  if($datehold){  
    print "clef : $clef  valeur : $valeur  datehold : $datehold\n";  
  }else{  
    print "clef : $clef  valeur : $valeur\n";  
  }  
}  

__END__  
A1F712492D9B|info_46943_0_11111@domaine.com  
C55657BC738|info_48894_0_22222@domaine.com|20100826_121900  

~ $ perl champs_underscore.pl 
clef : A1F712492D9B  valeur : info_46943_0_11111@domaine.com  

clef : C55657BC738  valeur : info_48894_0_22222@domaine.com  datehold : 20100826_121900



GNU/Linux:Linux is Not Ubuntu! Quel linux choisir ne veut pas dire votre Distribution préférée,
106485010510997108
1
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 569
26 août 2010 à 14:59
Re,

Tu peux aussi utiliser l'opérateur ?: si tu veux, pour faire plus court ;-)

#!/usr/bin/perl
use strict;use warnings;

while (<DATA>) {
  my ($clef,$valeur,$datehold) = split /\|/;
  $datehold
  ?
    print "clef : $clef  valeur : $valeur  datehold : $datehold\n"
  :
    print "clef : $clef  valeur : $valeur\n"
  ;
}

__END__
A1F712492D9B|info_46943_0_11111@domaine.com
C55657BC738|info_48894_0_22222@domaine.com|20100826_121900
0
sbouli Messages postés 200 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 14 août 2014 2
26 août 2010 à 15:23
excellent, le print n'est là que pour faire jolie, je vais stocker en tableau uniquement les entrées de moins de 2 jours et donc purger les autres.
Je vais donc parser la datehold et la matcher, DateTime est mon ami !

Merci beaucoup à tout les 2 !!

Stéphane
0
Leviathan49 Messages postés 257 Date d'inscription jeudi 10 juin 2010 Statut Membre Dernière intervention 22 juillet 2011 70
26 août 2010 à 12:44
Essaye Avec un regex de type ([^|]+)\|([^|]+)(?:\|([^|]+))?
(?: ) = parenthèse non capturantes.
0
sbouli Messages postés 200 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 14 août 2014 2
26 août 2010 à 13:42
je viens de tester avec The Regex Coach et ça ne semble pas faire ce que j'attends.

si je test sur une ligne avec uniquement 2 éléments, il poursuit sur la seconde ligne pour finir le second token.

si je test sur une ligne avec 3 éléments, il va finir le 3eme token sur la ligne suivante ....

au secours ...

Stéphane
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 569
26 août 2010 à 14:09
Salut,

Si j'ai bien compris, quelque soit le nombre de champs tu veux récupérer juste les 2 premiers?
0
sbouli Messages postés 200 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 14 août 2014 2
26 août 2010 à 14:12
bonjour lami,

non, je veux récupérer soit 2 champ soit 3 si le 3eme est présent.

2 formats possible pour chaque ligne :

champ1|champ2
ou
champ1|champ2|champ3

quand le champ3 n'existe pas, la variable vaut rien ou vide :

(($clef,$valeur,$datehold) = ([^|]+)\|([^|\s]+)(?:\|([^\s]+))?

ça me parait pas mal ....

Stéphane
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 569
Modifié par lami20j le 26/08/2010 à 14:15
Re,

Pour ce genre de situation split doit faire l'affaire vu qu'il y a un séparateur de champs.
Perso c'est comme ça que j'aurais fait (même si j'aime bien les regex ;-)

($clef,$valeur,$datehold) = split "/\|/";
0
sbouli Messages postés 200 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 14 août 2014 2
26 août 2010 à 14:30
ça marche pas .... pourtant c'est plus logique et simple que l'expression régulière ....

while (<FICHIER_HOLD_FROM>) {
        ($clef,$valeur,$datehold) = split "/\|/";
	print "clef : $clef  valeur : $valeur  datehold : $datehold\n";
}


donne :

Use of uninitialized value in concatenation (.) or string at /repertoire/fichier.pl line 112, <FICHIER_HOLD> line 1.
Use of uninitialized value in concatenation (.) or string at /repertoire/fichier.pl line 112, <FICHIER_HOLD_FROM> line 1.
clef : C55657BC738|infos_00000_0_111111@domaine.com
  valeur :   datehold :



avec la source :

# cat fichier_hold.dat
C55657BC738|infos_00000_0_111111@domaine.com
...
0
sbouli Messages postés 200 Date d'inscription jeudi 20 décembre 2007 Statut Membre Dernière intervention 14 août 2014 2
26 août 2010 à 14:09
parfais, non il n'y aura pas d'espace, j'aurais jamais pensé à utilisé l'espace !

bravo

maintenant je test en live sur un fichier ... monstrueux :)

a+

Stéphane
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 569
26 août 2010 à 14:12
Re,

Tu n'as pas répondu à ma question ;-)
0