Usar REGEX para hacer coincidir una cadena sin que el primer token se repita en la cadena. (PARTE 2)

Gracias a @cool_me5000 por ayudarme con una versión demasiado simplificada de esta pregunta aquí: PERL: uso de REGEX para hacer coincidir una cadena sin que el primer token se repita en la cadena. (ABC, no AAA ABC)

Aquí está la pregunta ajustada:

Estoy tratando de usar una expresión regular para hacer coincidir la PRIMERA instancia donde ATE es seguido por CAT sin otro ATE entre ATE y CAT. Quiero hacer coincidir con el "ATE BAT CAT". Tenga en cuenta que en esta cadena de texto hay otras instancias que siguen a la primera combinación ATE/CAT que también podrían encajar en ATE/CAT (observe específicamente el "ATE DOG CAT cerca del final de la cadena) Aquí está el texto:

$TEXT = "ATE ATE ATE ATE BAT CAT ATE DOG EGG ATE FOR GIN ATE DOG CAT ATE";

Primero intenté:

@finds1=$TEXT=~m/((ATE).*?(CAT))/;
$result = $finds1[0];
print "result = $result\n";

Esto imprime lo siguiente:

result = ATE ATE ATE ATE BAT CAT

Cuando lo que quiero es solo:

result = ATE BAT CAT

Tenga en cuenta que estoy tratando de crear una expresión regular que podría usarse donde B podría ser cualquier cadena de caracteres. Por ejemplo, ATE DOG CAT, ATE FAT GET HAT JOT KIN CAT, ATE YAK ULE INN OLD KOC JOG HUG GOT TAL CAT.

A continuación, traté de usar un look-forward combinado con una declaración if then else. Aquí está el código:

@finds1=$TEXT=~m/(ATE(?(?!.*?ATE.*?CAT).*?CAT|Z{100}))/;
$result = $finds1[0];
print "result = $result\n";

La primera parte de REGEX, (ATE, le dice a perl que busque una ocurrencia de ATE. Una vez que la encuentra, perl procesa la declaración if then else donde la declaración condicional es que no hay instancias de .?COMIÓ.?CAT siguiendo a ATE, si no se encuentra ninguno entonces perl busca .*?CAT, si se encuentra al menos uno, entonces busca 100 instancias de Z. (mi forma de hacer que Perl avance ya que ni en este texto ni en el texto que estoy tratando de analizar hay 100 Zs.)

Esto devuelve:

result = ATE DOG CAT    

He considerado usar una mirada positiva hacia atrás después de identificar CAT por primera vez. Sin embargo, como mencioné anteriormente, el número de caracteres entre la primera combinación ATE.CAT sin una A entre ellos es variable. Por lo que yo sé, PERL no puede hacer búsquedas retrospectivas de longitud variable.

¡Cualquier ayuda o dirección que pueda proporcionar sería MUY apreciada!

Gracias de antemano!

preguntado el 04 de julio de 12 a las 02:07

1 Respuestas

Para la pregunta anterior, la solución fue:

my ($first) = $text =~ /(A[^AC]*C)/;

Usamos la negación de A|C entonces, eso significa que necesitamos usar la negación de ATE|CAT aquí.

Algo que todos deberían saber es que (?:(?!STRING).) es (?:STRING) as [^CHAR] es CHAR. (?:(?!PAT).) también funciona con algo patrones más complejos, incluido el anterior.

Entonces obtenemos:

my ($first) = $text =~ /(ATE (?:(?!ATE|CAT).)* CAT)/sx;

Explicación:

No quieres "CAT" o "ATE" entre "ATE" y "CAT", así que

   +---------------- You don't want CAT or ATE starting here.
   |+--------------- You don't want CAT or ATE starting here.
   ||--+------------ You don't want CAT or ATE starting here.
   ||   +----------- You don't want CAT or ATE starting here.
   ||   |+---------- You don't want CAT or ATE starting here.
   ||   ||
   vv   vv
ATE??...??CAT

Entonces eso sería

/
   ATE
   (?! CAT|ATE ) .
   (?! CAT|ATE ) .
   ...
   (?! CAT|ATE ) .
   (?! CAT|ATE ) .
   CAT
/x

La repetición se maneja usando *.

Respondido 04 Jul 12, 02:07

perldoc.perl.org/perlre.html#Extended-Patrones desplácese hasta "Afirmaciones de revisión" si desea saber cómo funciona esto :) - Albañil de piedra

¡Esto es genial! ¡Gracias por presentarme a los grupos sin captura! - user1500158

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.