Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3203 connectés 

  FORUM HardWare.fr
  Programmation
  Perl

  [Perl] extraction de chaine

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Perl] extraction de chaine

n°958234
sasame
Posté le 21-01-2005 à 09:37:51  profilanswer
 

Bonjour,
 
Je cherche une expression reguliere qui puisse ranger dans une variable, une chaine de caractere qui se trouve entre 2 chaines.
 
ex :
 
Probleme Description:
Tout est planter(test)
 
Resolution.
 
j'ai esseyer ça:
 

Code :
  1. push @description, $1 if /Probleme Description\s+(.+)^/


 
mais ça marche pas ça ne va pas chercher a la ligne suivante.
Si quelqu'un connaissai l'astuce, ça me serai grandement utile.
 
Merci.

mood
Publicité
Posté le 21-01-2005 à 09:37:51  profilanswer
 

n°959777
maximew
Coffee and cigarettes and Cate
Posté le 23-01-2005 à 11:50:01  profilanswer
 

Fait un tr/\n\r//d; sur la ligne précédente et ca devrait marcher normalement...
 
push @description,$2 if m/^(Probleme Description\s+)(.+?)(\s+Resolution)/;


---------------
Mon Flickr
n°960685
sasame
Posté le 24-01-2005 à 13:54:34  profilanswer
 

je te remercie de ta reponse mais ça n'a pas l'air de marcher   :(

n°961105
matafan
Posté le 24-01-2005 à 20:12:27  profilanswer
 

perl -e 'local $/; $_=<>; /^Probleme Description:(.*)^Resolution/ms; print $1'


 
Le //s permet de traiter les chaines multi-lignes comme une seule ligne. Le //m permet de faire matcher ^ et $ avec les debut de ligne et fin de ligne, au lieu des debut de chaine et fin de chaine.


Message édité par matafan le 24-01-2005 à 20:13:04
n°961599
sasame
Posté le 25-01-2005 à 09:46:37  profilanswer
 

Ha je te remercie grandement pour ton aide ça marche.
 
Par contre je comprend pas bien le

Code :
  1. local $/

et le

Code :
  1. $_=<>


 
Pourrai tu m'éclairer là dessus?
Merci.

n°961645
pospos
Posté le 25-01-2005 à 10:33:53  profilanswer
 

$/ est une variable speciale qui indique à Perl le separateur de ligne à utiliser kand il lit un fichier.
En temps normal il vaut \n (ou \r\n).
 
<> est l'entrée standard (clavier), ca equivaut à <STDIN>, ca lit donc l'entrée standar en s'arrettant à chaque ligne... enfin à chaque fois qu'il rencontre la valeur de $/.
Dans ce cas precis $/ a été "effacé" (local redefini la variable dans le scope, et comme rien ne lui est assigné elle vaut undef), et plus rtien n'arrettera donc la lecture (sauf un fin de fichier, ou un ctrl-Z dans le cas de l'entrée standard).
on utilise souvent cette technique pour "slurper" un fichier d'un seul coup dans une variable:
 

Code :
  1. my $fichier = do{
  2.   local $/=undef; # ou local $/ tout court
  3.   <IN>;
  4. }


 
ou met tout ca dans un bloc (ou ici un do{}) pour ne pas modifier la valeur de $/ dans le reste du script (et dans les modules). c'est tres important car ca peut affecter d'autres parties du code. donc jamis de "$/=undef" sans "local" et sans bloc autour!
 
Sinon... dans ce cas precis $/ et <> ne servait qu'à illustrer le fonctionnement de la regexp...


Message édité par pospos le 25-01-2005 à 10:34:16
n°961658
sasame
Posté le 25-01-2005 à 10:46:30  profilanswer
 

Merci pour ta réponse.
 
dans mon cas vu que je veux recupéré d'autre chaine de caractere, j'ajoute  dans ma boucle while qui lit mon fichier
 

Code :
  1. push @description, $1 if /^Problem Description:(.*)^Problem Resolution/ms;
  2. push @call, $1 if /Help Desk Call\s+(.+)$/;

 
 
avec la derniere ligne là je veux extraire ce qu'il y a derriere "Help Desk Call" (il s'agit d'un numero).
Cette expression reguliere fonctionne, je l'ai tester plusieur fois.
Mais quand je l'insere dans la boucle et que je fait un "print @call", cela ne m'ffiche rien du tout.

n°961668
pospos
Posté le 25-01-2005 à 10:51:11  profilanswer
 

ha...
si tu lit ton fichier dans une boucle sans avoir modifié la variable $/ il va le lire ligne par ligne... et donc tu ne pourra pas utiliser ta regexp...
la solution consiste à avoir ton fichier ENTIER dans une variable, et d'appliquer ensuite ta regexp dessus. Pour faire ca soit tu concatene ta variable dans ta boucle while puis tu match ensuite, soit tu fais comme indiqué au dessus. Par exemple un petite fonction que j'utilise souvent:
 

Code :
  1. my $a = slurp("blabla.txt" );
  2. $a =~ ....
  3. sub slurp {
  4. my $file = shift;
  5. my $fh;
  6. if (UNIVERSAL::isa($file, 'GLOB')) {
  7.  $fh = $file;
  8. } else {
  9.  open($fh, '<', $file) || return undef;
  10. }
  11. binmode $fh;
  12. if (wantarray) {
  13.  <$fh>
  14. } else {
  15.  local $/;
  16.  <$fh>
  17. }
  18. <$fh>
  19. }


Message édité par pospos le 25-01-2005 à 11:31:20
n°961684
sasame
Posté le 25-01-2005 à 11:11:57  profilanswer
 

Houla j'ai pas tout compris  :??:  
 
voila mon code :
 

Code :
  1. #!/usr/bin/perl -w
  2. use strict;
  3. my ( @call, @description, @resolution, @id1, @id2, $fav, $ligne );
  4. $fav = "toto1.txt";
  5. open AVANT, $fav or die "Impossible d'ouvrir $fav\n";
  6. local $/;
  7.     while (<AVANT> )
  8.         {
  9.         #Recherche du numero de la demande
  10.         push @call, $1 if /Help Desk Call\s+(.+)$/ ;
  11.         #Recherche de la description de la demande
  12.         push @description, $1 if /^Problem Description:(.*)^Problem Resolution/ms;
  13.         #Recherche de la resolution de la demande
  14.         push @resolution, $1 if /^Problem Resolution:(.*)^Opened By/ms;
  15.         #Recherche de l'id1
  16.         push @id1, $1 if /Opened By\s+(.+)$/ ;
  17.         #Recherche de l'id2
  18.         push @id2, $1 if /Sent To\s+(.+)$/ ;
  19.         }
  20.         print ("\nObjet : Enregistrement de la demande numero @call \n" );
  21.         print ("\nDescription de la demande: @description \n" ) ;
  22.         print ("Description de la resolution: @resolution \n" );
  23.         print ("\nOuvert par:   @id1 \n" );
  24.         print ("Envoye a:       @id2 \n\n" );
  25. close AVANT;


 
ça ne me renvoie ni @call, ni @id1
 
mon fichier toto1.txt se presente comme ça :
 

Code :
  1. Objet : Event Notification For: Help Desk Call #20378
  2. Problem Description:
  3. Tout est planter (test)
  4. Problem Resolution:
  5. Plus rien n'est plante
  6. Opened By               JD: Dupont, Jean
  7. Sent To                 IN: inconnu


 
Si tu pouvais m'aider ça serai sympa, ça fait 3 semaines que je galere dessus  :(

n°961719
pospos
Posté le 25-01-2005 à 11:43:28  profilanswer
 

Code :
  1. use strict;
  2. $_ = slurp("toto1.txt" );
  3. #Recherche du numero de la demande
  4. my ($call) =  /Help Desk Call\s+([^\r\n]*)/ ;
  5. #Recherche de la description de la demande
  6. my ($description) = /Problem Description:(.*?)Problem Resolution:/ms;
  7. #Recherche de la resolution de la demande
  8. my ($resolution) = /^Problem Resolution:(.*?)Opened By/ms;
  9. #Recherche de l'id1
  10. my ($id1) = /Opened By\s+([^\r\n]*)/;
  11. #Recherche de l'id2
  12. my ($id2) = /Sent To\s+([^\r\n]*)/;
  13. print ("\nObjet : Enregistrement de la demande numero $call \n" );
  14. print ("\nDescription de la demande: $description \n" ) ;
  15. print ("Description de la resolution: $resolution \n" );
  16. print ("\nOuvert par:   $id1 \n" );
  17. print ("Envoye a:       $id2 \n\n" );
  18. sub slurp {
  19. my $file = shift;
  20. my $fh;
  21. if (UNIVERSAL::isa($file, 'GLOB')) {
  22.  $fh = $file;
  23. } else {
  24.  open($fh, '<', $file) || return undef;
  25. }
  26. binmode $fh;
  27. if (wantarray) {
  28.  <$fh>
  29. } else {
  30.  local $/;
  31.  <$fh>
  32. }
  33. }


 
si je puis me permettre, ton format de fichier n'est pas tres robuste. Que se passe t-il par exemple si l'utilisateur ecrit 'Opened By' dans le champ 'Problem Resolution'?

mood
Publicité
Posté le 25-01-2005 à 11:43:28  profilanswer
 

n°961744
sasame
Posté le 25-01-2005 à 12:01:21  profilanswer
 

Merci vraiment beaucoup (ça se dit ça?)
Tu me sauve la vie là, sur 3 semaines que je rame dessus, toi en quelque minutes tu fais tout marcher.
Je suis vraiment pas fait pour le développement ^^;
 
En fait ce que je dois faire c'est réaliser un filtre sur un serveur de messagerie.
Des mails avec le texte que j'ai mis sont envoyer sur le serveur de messagerie. Le filtre reécupére les variables demander, en autre le numero, un description,... , met ça dans un autre fichier pour le reformuler apres, (voir les print).
 
Pour remaitre les variable dans un autre fichier, j'ai pensé a faire un fichier de référence, avec des nom de variable à remplacer par substitution en fait,
 
ex : Problem description:
desc1
 
je remplace desc1 par la chaine que j'ai extraite dans @description et j'enregistre le tout dans un autre fichier
donc en tout 3 fichiers, un avant, un de référence, et un apres.
 
Bon pour l'instant je suis rester sur ce model là mais si tu as d'autre conseil pour m'aider à améliorer le filtre je suis preneur.
 
Pas besoin de faire des testes sur les mot extrait vu que le fichier "avant" ne change jamais"

n°961917
pospos
Posté le 25-01-2005 à 14:35:14  profilanswer
 

ouai la subsitution dans un fichier de reference c'est pas mal, c'est un petit systeme de template en fait. rajoute un symbole autour, genre %desc1% pour etre certain qu'il n'y aura pas de conflict
 
tu slurp ton fichier de template, tu fait les subsitutions avec les bonnes valeurs, et tu le print dans un nouveau fichier.
 
par exemple:
 

Code :
  1. ...code precedent...
  2. my %replace = (
  3. call  => $call,
  4. description => $description,
  5. resolution => $resolution,
  6. id1  => $id1,
  7. id2  => $id2,
  8. );
  9. my $replace_regexp = join('|', keys %replace);
  10. $replace_regexp = qr/%($replace_regexp)%/;
  11. my $template = slurp("reference.txt" );
  12. $template =~ s/$replace_regexp/$replace{$1}/eg;
  13. print $template;


 
apres tu met tout ca proprement dans des subs (en gardant peut etre le contenu du template original dans une variable pour eviter de devoir recharger le fichier à chaque fois)

n°961995
matafan
Posté le 25-01-2005 à 15:28:01  profilanswer
 

<> c'est pas stdin, c'est l'entrée par défaut... Nuance ;) En particulier si un fichier est passé en paramêtre à Perl, alors <> lit ce fichier, pas stdin : perl -e '...' mon_fichier


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Perl

  [Perl] extraction de chaine

 

Sujets relatifs
[c] transformer une chaine en entierHistoire de chaine
[Fortran 95] Conversion de types numériques en chaine de caractèresimposer une fin de chaine par une touche particulière
[Perl] Comment vérifier si un nombre est entier ?[PERL et DBI] probleme sur bind_param... [TROUVE]
[CGI-PERL] comment activer perl sur apache version windows ?concaténation de chaîne - jdk 1.5
Formatage d'un caractère spécial dans une chaineTrouver un mot dans une chaine de caracteres
Plus de sujets relatifs à : [Perl] extraction de chaine


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR