Qual è il motivo tecnico per cui “l’affermazione del lookbehind DEVE essere di lunghezza fissa” in regex?

Ad esempio, la regex riportata di seguito causerà la mancata definizione della lunghezza dell’asserzione del report di ricerca in background :

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

Questo tipo di restrizione non esiste per lookahead .

Lookahead e lookbehind non sono così simili come implicano i loro nomi. L’espressione lookahead funziona esattamente come se fosse un’espressione regolare autonoma, eccetto che è ancorata alla posizione corrente della partita e non consuma ciò che corrisponde.

Lookbehind è una storia completamente diversa. Partendo dalla posizione corrente della partita, fa scorrere indietro il testo di un carattere alla volta, cercando di abbinare la sua espressione in ogni posizione. Nei casi in cui non è ansible una corrispondenza, il lookbehind deve andare fino all’inizio del testo (un carattere alla volta, ricorda) prima che si arrenda. Confrontalo con l’espressione lookahead, che viene applicata esattamente una volta.

Questa è una grossolana semplificazione, ovviamente, e non tutti i sapori funzionano in questo modo, ma tu hai l’idea. Il modo in cui vengono applicate le schermate è fondamentalmente diverso (e molto, molto meno efficiente) rispetto al modo in cui vengono applicati i punti di vista. Ha senso solo porre un limite a quanto deve apparire indietro il lookbehind.

Prima di tutto, questo non è vero per tutte le librerie di espressioni regolari (come .NET).

Per PCRE, la ragione sembra essere:

L’implementazione delle asserzioni lookbehind è, per ogni alternativa, per spostare temporaneamente la posizione corrente indietro della larghezza fissa e quindi provare a far corrispondere.

(almeno, secondo http://www.autoitscript.com/autoit3/pcrepattern.html ).

PCRE non supporta il floating lookbehind perché può causare grossi problemi di prestazioni. Ciò è dovuto alla mancanza di capacità di corrispondenza da destra a sinistra: PCRE può avviare un ramo solo da una sinistra fissa, ma il lato sinistro di una lunghezza variabile non può essere riparato.

In generale, se ansible, provare a diramare la parte del tuo aspetto rispetto ai modelli a lunghezza fissa. Ad esempio invece di:

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

(1) utilizzare questo:

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

(2) O con \K :

 (src|href)="\Ketc. 

Nota che \K non è un vero lookbehind, perché avvia sempre la ricerca alla fine della partita precedente (nessun potenziale backstep nella partita precedente).

(3) In alcuni casi complessi di sola ricerca è ansible cercare con un'espressione "invertita" di lookahead in una stringa invertita. Non troppo elegante ma funziona:

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

Ho avuto lo stesso problema e l’ho risolto usando (?: subexpression)

Definisce un gruppo non di cattura. come Write(?:Line)? “WriteLine” in “Console.WriteLine ()” “Scrivi” in “Console.Write (valore)”

Ho dovuto cambiare il Regex sotto il quale suppongo di cogliere prima , o qualcosa all’inizio della stringa che mi stava dando un’asserzione dietro l’altra non è una lunghezza fissa .

 (?<=,|^) 

con questo,

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