PERL: uso de REGEX para hacer coincidir una cadena sin que el primer token se repita en la cadena. (ABC, no AAA ABC)

Soy relativamente nuevo en perl y me disculpo de antemano si esta pregunta es simple y me estoy perdiendo algo completamente obvio, sin embargo, he estado buscando la respuesta durante un par de días y no puedo encontrar una solución.

Estoy tratando de usar una expresión regular para que coincida con la PRIMERA instancia donde A es seguida por C sin otra A entre A y C. Tenga en cuenta que en esta cadena de texto hay otras instancias que siguen a la primera combinación de CA que también podrían encajar en la CA, (específicamente tenga en cuenta el ADC) Aquí está el texto:

$text = "AAA ABC ADE AFG ADC AHI AJK AIZ XXB NBV";

Primero intenté:

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

Esto imprime lo siguiente:

result = AAA ABC

Cuando lo que quiero es solo:

result = ABC

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 ADC, AFGHJKC, AYUIOKJHGTC.

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/(A(?(?!.*?A.*?C).*?C|Z{100}))/;
$result = $finds1[0];
print "result = $result\n";

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

Esto devuelve:

result = ADC    

He considerado usar una mirada positiva hacia atrás después de identificar C por primera vez. Sin embargo, como mencioné anteriormente, el número de caracteres entre la primera combinación AC 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 00:07

¿Estoy equivocado en mi interpretación de que /A[b-zB-Z]*?C/ encajaría a la perfección? -

Estás en lo correcto. Funciona en este texto. Gracias por su respuesta. ¿Cómo lo modificaría para acomodar los espacios entre la A y la C (por ejemplo, $texto = "AAA ABC ADE AFG ADC AHI AJK AIZ XXB NBV"; -

Aquí, lo ampliaré para que sea digno de respuesta, y también responderé su pregunta allí. -

Así: /A\s*[b-zB-Z]*?\s*C/ -

Realmente, no hay absolutamente ninguna razón para ser tan complicado. /A[b-zB-Z\s]*?C/ también funciona y es mucho más simple. -

2 Respuestas

¿No quieres simplemente

/A[^AC]*C/

Respondido 04 Jul 12, 01:07

Por lo que puedo decir, estás deseando:

  • Una "A"
  • Seguido de cualquier número de caracteres que no sean A
  • Seguido de una "C"

Esto se puede lograr con la expresión regular

/A[B-Z]*?C/

Caracteres entre corchetes [] representar una clase de personaje. Con una clase de carácter, puede decirle al motor de expresiones regulares que coincida solo con uno de varios caracteres. Simplemente coloque los caracteres (o rangos de caracteres) que desea hacer coincidir entre corchetes (http://www.regular-expressions.info/charclass.html). Digamos que querías hacer esto con otra letra, Q, tendrías una clase de personaje ligeramente diferente

/Q[A-PR-Z]*?C/

Si quisiera modificarlo para acomodar espacios entre la A y la C, puede abordarlo de dos maneras diferentes. Puedes negar una clase de personaje y coincidirá cualquier carácter aparte de los que están en él, así:

/A[^AC]*C/

Que coincidirá con una A, luego con cualquier número de caracteres además de A y C, luego con una C.

O, puede agregar un espacio a la clase de carácter original, así:

/A[B-Z ]*?C/ (tenga en cuenta el espacio después de la Z)

Si desea algún tipo de espacio en blanco, reemplace el espacio con \s, que representa cualquier espacio en blanco, así:

/A[B-Z\s]*?C/

Respondido 04 Jul 12, 01:07

Gracias por la gran respuesta. Tienes razón. Mi pregunta era bastante simple. Aunque su respuesta responde a cómo formulé mi pregunta, no aborda mi problema. Esto es completamente mi culpa. Lo que mejor lo abordaría es si hubiera hecho el texto de la siguiente manera: "$texto = comió comió comió bate gato comió perro huevo comió para ginebra ate perro gato comió"; Ahora, en lugar de extraer ABC, quiero extraer la primera vez que ate va seguida de cat sin ate entre ate y cat. - user1500158

¡Sí, eso es definitivamente más difícil! - Albañil de piedra

¿Alguna idea sobre cómo manejarlo? ¿Crees que debería publicar una nueva pregunta con el texto actualizado? De nuevo, gracias por tu ayuda. - user1500158

Lo pensare. Creo que sé cómo lo haría, pero podría no ser la expresión regular más eficiente o bonita del mundo. - Albañil de piedra

En este punto, tomaría el código funcional más feo que existe. - user1500158

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