Qual é a razão técnica para “lookbehind assertion deve ser o comprimento fixo” em regex?

Por exemplo, o regex abaixo fará com que o relatório de falha lookbehind assertion não tenha comprimento fixo :

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

Esse tipo de restrição não existe para lookahead .

Lookahead e lookbehind não são tão semelhantes quanto os seus nomes implicam. A expressão lookahead funciona exatamente da mesma forma que se fosse uma regex autônoma, exceto que está ancorada na posição atual da correspondência e não consome o que corresponde.

Lookbehind é uma história totalmente diferente. Começando na posição de correspondência atual, ela retrocede o texto, um caractere por vez, tentando corresponder sua expressão a cada posição. Nos casos em que nenhuma correspondência é possível, o lookbehind tem que ir até o início do texto (um caractere de cada vez, lembre-se) antes de desistir. Compare isso com a expressão lookahead, que é aplicada exatamente uma vez.

Isso é uma simplificação grosseira, é claro, e nem todos os sabores funcionam dessa maneira, mas você entende a ideia. A maneira como as lookbehinds são aplicadas é fundamentalmente diferente (e muito, muito menos eficiente do que) da maneira como lookaheads são aplicados. Só faz sentido colocar um limite em quanto tempo atrás o lookbehind tem que parecer.

Primeiro de tudo, isso não é verdade para todas as bibliotecas de expressões regulares (como o .NET).

Para PCRE, o motivo parece ser:

A implementação de asserções lookbehind é, para cada alternativa, mover temporariamente a posição atual de volta pela largura fixa e então tentar corresponder.

(pelo menos, de acordo com http://www.autoitscript.com/autoit3/pcrepattern.html ).

O PCRE não suporta lookbehind flutuante porque pode causar grandes problemas de desempenho. Isso ocorre devido à falta de capacidade de correspondência da direita para a esquerda: o PCRE pode iniciar uma ramificação somente a partir de uma esquerda fixa, mas a esquerda de uma lookbehind de comprimento variável não pode ser corrigida.

Geralmente, tente ramificar sua parte lookbehind para padrões de comprimento fixo, se possível. Por exemplo, em vez de:

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

(1) use isto:

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

(2) Ou com \K :

 (src|href)="\Ketc. 

Note que o \K não é um lookbehind real, porque sempre inicia a busca no final da partida anterior (nenhum retorno em potencial para a partida anterior).

(3) Em alguns casos complexos lookbehind-only, você pode pesquisar com uma expressão lookahead "invertida" em uma string invertida. Não é muito elegante, mas funciona:

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

Eu tive o mesmo problema e consertei usando (?: subexpression)

Define um grupo não capturado. como Write(?:Line)? “WriteLine” em “Console.WriteLine ()” “Write” em “Console.Write (valor)”

Eu tive que mudar o Regex abaixo, que é suposto pegar antes , ou algo no início da string que estava me dando lookbehind afirmação não é o comprimento fixo .

 (?<=,|^) 

com isso,

 (?:(?<=,)|^) 
 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 
    Intereting Posts