Extraire un mot d'une ligne suivant ce qui l'encadre

Extraire un mot d'une ligne suivant ce qui l'encadre - Perl - Programmation

Marsh Posté le 09-06-2011 à 16:08:19    

Bonjour,
 
je développe un petit script en perl (pour l'utilité et aussi pour apprendre), et j'ai besoin d'extraire un mot d'une ligne.
En fait je lit un fichier ligne par ligne.
 
Exemple de fichier
bla
bla
bla.all
all blabla
retour ALL;
ball
return all return;
 
Donc, je cherche a extraire des lignes le mot "all" seulement (sans distinction de casse). Il peut être encadré par :
des espaces
des tabulation
une fin de ligne
un début de ligne
un point (.)
un point virgule (;)
 
mais rien d'autres.
 
Je suis arrivé (mais sans grand résultat) à l'expression suivante :

Code :
  1. /[\s.]*all[\s;]/i


 
mais je n'obtiens pas la ligne 3 ("bla.all" )
 
merci de vos réponses.


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
Reply

Marsh Posté le 09-06-2011 à 16:08:19   

Reply

Marsh Posté le 09-06-2011 à 19:26:18    

/(^|[\s\t.;])all([\s\t.;]|$)/oi
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 09-06-2011 à 21:28:40    

Ah oui forcement, j'étais mal parti.
D'abord merci beaucoup.

 

Puis, je connais le i, que signifie le 'o' aprés le dernier / ?

 

Je dis peut être une ânerie mais \t n'est pas compris dans \s?


Message édité par le fou le 09-06-2011 à 21:30:09

---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
Reply

Marsh Posté le 10-06-2011 à 11:01:05    

Citation :

Je dis peut être une ânerie mais \t n'est pas compris dans \s?

Tout a fait, j'ai tapé sans me relire (juste fait un test rapide avec un script).
C'est /(^|[ \t.;])all([ \t.;]|$)/oi qui correspond exactement à tes specs. Ou bien /(^|[\s.;])all([\s.;]|$)/oi si la notion d'espace de ta spec ne désigne pas que le blanc..

Citation :

Puis, je connais le i, que signifie le 'o' aprés le dernier / ?

o = once: on ne compile qu'une fois l'expression, car rien a l'intérieur ne va changer à chaque pattern matching. C'est une optimisation et une bonne habitude à prendre.
A+,
 
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 10-06-2011 à 11:33:01    

Merci beaucoup Gilou pour tes explications.
 
Tu as raison, j'avais oublié de spécifier ce que j'entendais par blanc (espaces et/ou tab)
 
Euh, excuses moi, j'ai encore une question :
 
Dans l'absolut je voudrais utiliser cette expression pour recherche plusieurs mots. C'est à dire j'ai une liste de mots, et je voudrais faire cette recherhe avec chaque mots de la liste.
 
J'ai donc :
 

Code :
  1. my @liste  = ("all", "wait", "abs" );
  2. foreach $item (@liste)
  3. {
  4.     if ( //(^|[\s.;])$item([\s.;]|$)/oi )
  5.     {
  6.         print "mot trouve\n";
  7.     }
  8.     else
  9.     {
  10.         print "mot non trouve\n";       
  11.     }
  12. }


 
Cependant, il ne prend pas $item comme étant une variable mais la chaine à chercher. Comme lui faire comprendre l'inverse?
 
Ps : j'imagine que dans ce cas, l'option o n'est plus utile puisque l'expression va changer suivant le mot. J'ai bon?


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
Reply

Marsh Posté le 10-06-2011 à 17:54:54    

Bon je me réponds tout seul.
Je suis un âne, bien que tu m'es expliqué que l'opérateur o  ne signifiait qu'il ne compilait l'expression qu'une fois. Or si je change la variable dedans ca risque de pas marcher.
 
Merci.


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
Reply

Marsh Posté le 10-06-2011 à 18:01:48    

Tout à fait.
Notes que si tu utilises l'option strict (use Strict;) qui est recommandée, il vaudrait mieux écrire:
foreach my $item (@liste)
et d'autre part, pour //(^|[\s.;])$item([\s.;]|$)/oi il y aurait pas un / en trop au début?
 
A+,


Message édité par gilou le 10-06-2011 à 18:02:08

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 10-06-2011 à 19:07:12    

Pour trouver les mots d'une liste dans un texte donné, voici un exemple, pas nécessairement le plus optimal.

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use Tie::File;
  6.  
  7. my @testitems = qw(all wait abs return);  # les mots a trouver
  8. my $filename = 'texttest.txt'; # le texte
  9. my %result; # un hash, qui va en sortie contenir pour chaque mot de la liste, le de lignes le contenant
  10.  
  11. tie my @array, 'Tie::File', $filename or die "$!\n"; # pour utiliser un fichier comme un array
  12. foreach my $item (@testitems) {
  13.  $result{$item} = grep {/(^|[\s.;])$item([\s.;]|$)/i} @array; #construction du hash
  14. }
  15. untie @array;
  16.  
  17. print "items found: ";
  18. foreach my $item (@testitems) {
  19.  print "$item " if ($result{$item});
  20. }
  21. print "\n";


#construction du hash:  
grep {/(^|[\s.;])$item([\s.;]|$)/i} @array; retourne une liste des lignes de array ou l'expression régulière donnée est trouvée
comme on est dans un contexte scalaire, $result{$item} = va avoir pour effet d'assigner le nb d'éléments de cette liste à $result{$item}, et donc 0 si $item n'a pas été trouvé.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-06-2011 à 13:37:50    

Salut Gilou,
 
Merci pour tes réponses.
 
En fait, je me suis mal exprimé dés le début, ce que je voudrais en réalité, c'est afficher les lignes ou au moins l'un des ces mots clés n'est pas en majuscules.
 
 


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
Reply

Marsh Posté le 14-06-2011 à 20:18:53    

Un truc comme ça alors:

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. my @testlist = ("Alias Toto", "alias TUTU TOTO", "TOTO ALIAS", "AlIAS TOTO", "TUTU haha" ); # pour tester
  6. my @words = qw(alias toto tutu); # les mots clés
  7. my $regexp = "(". join('|', map {uc($_)} @words) . " )"; # (ALIAS|TOTO|TUTU) ici
  8.  
  9. foreach my $line (@testlist) {
  10.  local $_ = $line;
  11.  if (/$regexp/io) { # on saute les lignes sans mots clés
  12.    s/(^|\s)$regexp(?=\s|$)//go; # on vire les mots clés en majuscule
  13.    print  "$line\n" if (/$regexp/io); # on imprime la ligne s'il reste un mot clé
  14.  }
  15. }


L'idée: sur les lignes qui ont au moins un mot clé, on vire tous les mots clés en majuscule qui y figurent, et si on y trouve encore un mot clé, c'est qu'il y avait au moins un mot clé qui n'était pas en majuscule.
On pourrait se passer de la ligne 11, i.e. on vire tous les mots clés en majuscule de toute ligne, et si on y trouve encore un mot clé, c'est qu'il y avait au moins un mot clé qui n'était pas en majuscule dans la ligne, mais ça fait traiter inutilement des lignes et n'est pas optimal.
J'ai écrit la partie entre les lignes 9 et 15 pour que ce soit assez optimal (je vois pas trop comment optimaliser plus) et que ça ne modifie pas ce qu'on teste (cas par exemple ou la liste est en fait un fichier lié avec Tie::File).
Note: le blanc qui apparaît avant la parenthèse fermante de la définition de $regexp est un artéfact du code d'affichage du forum.
A+,


Message édité par gilou le 14-06-2011 à 23:05:50

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed