2010-06-26 4 views
5

estoy aprendiendo Perl y notado una peculiaridad bastante peculiar - tratar de coincidir con una de varias condiciones de expresiones regulares en un rato resultados de bucle en bucle que pasa para el infinito:Perl: ¿Múltiples condiciones globales de expresiones regulares "o" separadas en el bloque conduce a un bucle infinito?

#!/usr/bin/perl 

my $hivar = "this or that"; 

while ($hivar =~ m/this/ig || $hivar =~ m/that/ig) { 
     print "$&\n"; 
} 

La salida de este programa es:

this 
that 
that 
that 
that 
[...] 

Me pregunto por qué es esto? ¿Hay alguna solución que son menos torpe que esto:

#!/usr/bin/perl 

my $hivar = "this or that"; 

while ($hivar =~ m/this|that/ig) { 
     print "$&\n"; 
} 

Ésta es una simplificación de un problema del mundo real que estoy encontrando, y mientras yo estoy interesado en esto en un punto de vista práctico, también me gustaría saber qué detrás de las escenas está desencadenando este comportamiento. Esta es una pregunta que no parece ser muy compatible con Google.

Gracias!

Tom

+0

hobbes lo explicaron muy bien a continuación, pero también lo hacen Wall, Schwartz, et al .: http://perldoc.perl.org/perlretut.html#Global-matching – msw

+0

Es posible que desee ver aquí para ver si el Regexp :: Ensamblar paquete puede ayudarlo: http://stackoverflow.com/questions/1478083/how-can-i-efficiently-match-many-different-regex-patterns-in-perl –

Respuesta

16

Lo que pasa es que hay un valor oculto asociado con cada cadena , no con cada partido, que controla en un partido /g intentará continuar, y accesible a través pos($string). Lo que ocurre es:

  1. pos($hivar) es 0, /this/ partidos en la posición 0 y restablece pos($hivar) a 4. El segundo partido no se intenta o porque el operador ya es una realidad. $& se convierte en "esto" y se imprime.
  2. pos($hivar) es 4, /this/ no coincide porque no hay "esto" en la posición 4 o posterior. La coincidencia que falla restablece pos($hivar) a 0.
  3. /that/ coincide en la posición 6 y restablece pos($hivar) a 10. $& se convierte en "eso" y se imprime.
  4. pos($hivar) es 10, /this/ no coincide porque no hay "esto" en la posición 10 o posterior. La coincidencia que falla restablece pos($hivar) a 0.
  5. /that/ coincide en la posición 6 y restablece pos($hivar) a 10. $& se convierte en "eso" y se imprime.

y los pasos 4 y 5 se repiten indefinidamente.

Adición de la bandera de expresiones regulares c (que le dice al motor no volver a cero en un partido de pos fallado) resuelve el problema en el código de ejemplo que nos ha facilitado, pero puede o no ser la solución ideal para un problema más complejo.

+2

realmente bien explicado, cookie para usted. – Prix

+0

De hecho. Así poner. ¡Gracias! –

Cuestiones relacionadas