2009-08-18 9 views
3

J'ai du code qui saisit le "entre" d'un texte; spécifiquement, entre un foo $someword et le suivant foo $someword.Pourquoi mon regex Perl provoque-t-il une boucle infinie?

Cependant, ce qui se passe est qu'il se bloque au premier "entre" et en quelque sorte la position de la chaîne interne ne s'incrémente pas. Les données d'entrée sont un fichier texte avec des sauts de ligne ici et là: ils sont plutôt hors de propos, mais facilitent l'impression.

my $component = qr'foo (\w+?)\s*?{'; 

while($text =~ /$component/sg) 
{ 
    push @baz, $1; #grab the $someword 
} 

my $list = join("|", @baz); 
my $re = qr/$list/; #create a list of $somewords 

#Try to grab everything between the foo $somewords; 
# or if there's no $foo someword, grab what's left. 

while($text=~/($re)(.+?)foo ($re|\z|\Z)/ms) 
#if I take out s, it doesn't repeat, but nothing gets grabbed. 
{ 
# print pos($text), "\n"; #this is undef...that's a clue I'm certain. 
    print $1, ":", $2; #prints the someword and what was grabbed. 
    print "\n", '-' x 20, "\n"; 
} 
+2

Vous ne voulez pas un «/g "modificateur dans la deuxième boucle aussi? – jrockway

+0

\ z et \ Z ne sont pas nécessaires, \ Z contient \ z –

+0

Je marche dans le texte, ne saisissant pas un tableau (qui est ce que g retournerait). Cependant,/g n'affecte pas le problème de sortie finale. J'ai essayé. :-) –

Répondre

4

Mise à jour: Encore une mise à jour pour faire face à 'foo' survenant à l'intérieur du texte que vous souhaitez extraire:

use strict; 
use warnings; 

use File::Slurp; 

my $text = read_file \*DATA; 

my $marker = 'foo'; 
my $marker_re = qr/$marker\s+\w+\s*?{/; 

while ($text =~ /$marker_re(.+?)($marker_re|\Z)/gs) { 
    print "---\n$1\n"; 
    pos $text -= length $2; 
} 

__DATA__ 
foo one { 
one1 
one2 
one3 

foo two 
{ two1 two2 
two3 two4 } 

that was the second one 

foo three { 3 
foo 3 foo 3 
foo 3 
foo foo 

foo four{} 

Sortie:

 
--- 

one1 
one2 
one3 


--- 
two1 two2 
two3 two4 } 

that was the second one 


--- 
3 
foo 3 foo 3 
foo 3 
foo foo 


--- 
} 
+0

A propos, oui. Je cherche tout après le {et avant le prochain foo. –

+0

Cela fonctionne. Sans le pos $ text - = 3, retourne le premier et le dernier. J'ai peur que je sois confus au sujet de * pourquoi * votre solution a fonctionné et ce qui n'allait pas avec le mien. Pensées? –

+0

En recherchant le '(?: Foo | \ Z)' avance 'pos $ text' de la longueur de' foo' s'il y a un truc. Par conséquent, la correspondance suivante commence après le 'foo' suivant sauf si' pos $ text' est réinitialisé à une position avant le prochain 'foo' qui est trois caractères avant la position actuelle. Si vous avez déjà atteint la fin de la chaîne, cela n'a pas d'importance. –

Questions connexes