2012-01-27 8 views
17

Estoy tratando de usar lookbehinds en una expresión regular y parece que no funciona como esperaba. Entonces, este no es mi uso real, pero para simplificar voy a poner un ejemplo. Imagine que quiero hacer coincidir "ejemplo" en una cadena que dice "esto es un ejemplo". Así, de acuerdo con mi comprensión de lookbehinds esto debería funcionar:La expresión regular Lookbehind no funciona con los cuantificadores ('+' o '*')

(?<=this\sis\san\s*?)example 

Lo que esto debe hacer es encontrar "Se trata de una", entonces los caracteres de espacio y finalmente coincide con la palabra "ejemplo". Ahora, no funciona y no entiendo por qué, ¿es imposible usar '+' o '*' dentro de lookbehinds?

También probé los dos y que funcionan correctamente, pero no cumplen mis necesidades:

(?<=this\sis\san\s)example 
this\sis\san\s*?example 

estoy usando este sitio para poner a prueba mis expresiones regulares: http://gskinner.com/RegExr/

+5

Esto necesita una etiqueta que identifica el idioma o el medio ambiente donde los usas Las expresiones regulares de .NET manejan esto sin problemas. – Joey

+0

¡Aviso! Si tu expresión regular funcionaría como quisieras, también coincidirá con 'example' de esto:' this is anexample'. Entonces, si no lo desea, debe eliminar el '?' – noob

+0

micha: Probablemente deberían simplemente cambiar el * por un '+'. Eliminar el '?' No tiene ningún efecto en ese sentido. Pero de hecho, '*?' Como cuantificador es inútil e innecesario en este caso ya que no hay más espacios en blanco para que coincida después de eso, por lo que '\ s *?' Es equivalente a '\ s *'. – Joey

Respuesta

15

Muchas bibliotecas de expresiones regulares no sólo permiten expresiones estrictas para ser utilizados en la mirada detrás de las afirmaciones como:

  • único partido cadenas de la misma longitud fija: (?<=foo|bar|\s,\s) (tres caracteres cada una)
  • única que coincida con las cadenas de longitudes fijas: (?<=foobar|\r\n) (cada rama con longitud fija)
  • sólo cadenas coinciden con una longitud límite superior: (?<=\s{,4}) (hasta cuatro repeticiones)

La razón de estas limitaciones se debe principalmente a que esas bibliotecas no pueden procesar las expresiones regulares al revés en todos o solo en un subconjunto limitado.

Otra razón podría ser evitar que los autores construyan expresiones regulares demasiado complejas que son difíciles de procesar ya que tienen un llamado pathological behavior (vea también ReDoS).

Véase también section about limitations of look-behind assertions en Regular-Expressions.info.

+0

En [mi respuesta a esta pregunta] (https://stackoverflow.com/questions/17286667/expresión-regular-utilizando-negativo-seguirán-no -working-in-notepad/48727748 # 48727748), he enumerado algunas estrategias/soluciones después de que encontré esta limitación en lookbehinds negativos. Espero que pueda ayudar a otros también! – Marathon55

0

mayoría de los motores de expresiones regulares Don' t admite expresiones de longitud variable para aserciones de búsqueda hacia atrás.

+1

Es solo el aspecto subyacente lo que es problemático. Lookahead puede ser cualquier cosa en todos los motores regex que lo soporten. – Joey

+0

@Joey true, editado para mayor precisión. :) – Amber

3

Lo dijo ámbar es cierto, pero se puede trabajar alrededor de ella con otro enfoque: Un paréntesis grupo no capturar

(?<=this\sis\san)(?:\s*)example 

que hacen que sea una longitud fija mirar hacia atrás, por lo que debería funcionar.

+1

Es lo mismo que '(? <= This \ sis \ san) \ s *? Example', lo que significa que también coincide con los espacios y para su información' (?: '') 'Hace que el proceso sea más lento. – noob

+0

micha, me preocuparía más la parte coincidente en ese caso que el rendimiento. Obtuve un promedio de 0.02451781 ms con el grupo que no captura y 0.02370844 ms sin él. No creo que sea una diferencia significativa. – Joey

+1

@micha No. No es lo mismo. Es un grupo * que no captura *. Mi expresión regular solo coincide con 'example' (sin los espacios iniciales), pero su ejemplo * incluye * espacios principales – Bohemian

9

Oye, si no estás usando la variable de python mira detrás de la aserción, puedes engañar al motor de expresiones regulares escapando de la coincidencia y comenzando de nuevo usando \K.

Este sitio explica bien .. .. http://www.phpfreaks.com/blog/pcre-regex-spotlight-k

Pero más o menos cuando se tiene una expresión que hacer coincidir y quiere conseguir todo detrás de él usando \ K obligará a empezar de nuevo ...

Ejemplo:

string = '<a this is a tag> with some information <div this is another tag > LOOK FOR ME </div>' 

juego /(\<a).+?(\<div).+?(\>)\K.+?(?=\<div)/ hará que la expresión regular para reiniciar después de hacer coincidir el div etiqueta final, por lo que la expresión regular que no incluirá en el resultado. El (?=\div) hará que el motor obtenga todo por delante de la etiqueta div final

+1

esto funciona con ruby ​​2.x pero falla con 1.9 y jruby 1.7.x; comentario original: bueno, me sorprende que nunca supe esta característica. Aprenda a formatear el código en el editor y no tendrá precio – akostadinov

+0

'\ K' en realidad es realmente útil. No sé lo que habría hecho sin eso ... –

0

Puede usar subexpresiones.

(this\sis\san\s*?)(example) 

Así que para recuperar el grupo 2, "ejemplo", $2 de expresiones regulares, o \2 si está usando una cadena de formato (como por del pitón re.sub)

Cuestiones relacionadas