¿Cuál es la razón técnica para “la aseveración de búsqueda DEBE ser de longitud fija” en expresiones regulares?

Por ejemplo, la siguiente expresión regular provocará que el informe de falla de la aseveración de búsqueda no sea de longitud fija :

#(?<!(?:(?:src)|(?:href))=["\']?)((?:https?|ftp)://[^\s\'"()]+)#S 

Tal clase de restricción no existe para el lookahead .

Lookahead y lookbehind no son tan similares como lo implican sus nombres. La expresión de búsqueda anticipada funciona exactamente igual que si fuera una expresión regular independiente, excepto que está anclada en la posición de coincidencia actual y no consume lo que coincide.

Lookbehind es una historia completamente diferente. Comenzando en la posición de coincidencia actual, retrocede el texto un carácter a la vez, intentando emparejar su expresión en cada posición. En los casos en que no es posible la coincidencia, el lookbehind tiene que recorrer todo el camino hasta el comienzo del texto (un personaje a la vez, recuerda) antes de que se rinda. Compare eso con la expresión de anticipación, que se aplica exactamente una vez.

Esta es una sobresimplificación burda, por supuesto, y no todos los sabores funcionan de esa manera, pero entiendes la idea. La forma en que se aplican los elementos subyacentes es fundamentalmente diferente de (y mucho, mucho menos eficiente que) la forma en que se aplican las miras. Solo tiene sentido establecer un límite sobre cuánto debe mirar el aspecto detrás.

En primer lugar, esto no es cierto para todas las bibliotecas de expresiones regulares (como .NET).

Para PCRE, la razón parece ser:

La implementación de aserciones de búsqueda hacia atrás es, para cada alternativa, mover temporalmente la posición actual hacia atrás por el ancho fijo y luego intentar hacer coincidir.

(al menos, de acuerdo con http://www.autoitscript.com/autoit3/pcrepattern.html ).

PCRE no es compatible con floating lookbehind porque puede causar problemas de rendimiento importantes. Esto se debe a la falta de capacidad de coincidencia de derecha a izquierda: PCRE puede iniciar una bifurcación solo a partir de una izquierda fija, pero a la izquierda de una bifurcación de longitud variable no puede corregirse.

En general, si es posible, intente dividir su parte posterior en patrones de longitud fija. Por ejemplo, en lugar de:

 (?< =(src|href)=")etc. 

(1) usa esto:

 (?:(?< =src=")|(?<=href="))etc. 

(2) O con \K :

 (src|href)="\Ketc. 

Tenga en cuenta que \K no es una imagen real detrás, porque siempre comienza la búsqueda al final de la coincidencia previa (sin posible retroceso en la coincidencia anterior).

(3) En algunos casos complejos de solo mirar detrás, puede buscar con una expresión de búsqueda anticipada "invertida" en una cadena invertida. No muy elegante, pero funciona:

 .cte(?="=(ferh|crs)) 

Tuve el mismo problema y lo solucioné usando (?: subexpression)

Define un grupo no capturable como Write(?:Line)? “WriteLine” en “Console.WriteLine ()” “Write” en “Console.Write (value)”

Tuve que cambiar la Regex a continuación, que se supone que debe detectar antes , o algo en el inicio de la cadena que me daba la afirmación de que la referencia no es de longitud fija .

 (?< =,|^) 

con este,

 (?:(?< =,)|^) 
 grep -P '(?< =((three)|(one)) )two' <<< "one two three three two one" grep: lookbehind assertion is not fixed length grep -P '((?<=(three) )|(?<=(one) ))two' <<< "one two three three two one" one two three three two one