Gruppi di bilanciamento in lookbehind a lunghezza variabile

TL; DR: L’ uso della cattura (e in particolare dei gruppi di bilanciamento) all’interno delle schermate di .NET modifica le acquisizioni ottenute, anche se non dovrebbe fare la differenza. Che cosa è con le schermate di .NET che rompono il comportamento previsto?

Stavo cercando di trovare una risposta a quest’altra domanda , come una scusa per giocare con i gruppi di bilanciamento di .NET. Tuttavia, non riesco a farli funzionare all’interno di un lookbehind a lunghezza variabile.

Prima di tutto, si noti che non intendo utilizzare questa particolare soluzione in modo produttivo. È più per ragioni accademiche, perché sento che sta succedendo qualcosa con lo sguardo a lunghezza variabile dietro il quale non sono a conoscenza. E sapendo che potrebbe tornare utile in futuro, quando effettivamente devo usare qualcosa del genere per risolvere un problema.

Considera questo input:

~(ab (c) d (ef (g) h) i) j (k (l (m) n) p) q 

L’objective è quello di abbinare tutte le lettere, che sono racchiuse tra parentesi precedute da ~ , non importa quanto sia profondo (quindi tutto da a a i ). Il mio tentativo era quello di verificare la posizione corretta in un lookbehind, in modo da poter ottenere tutte le lettere in una singola chiamata alle Matches . Ecco il mio modello:

 (?<=~[(](?:[^()]*|(?[(])|(?[)]))*)[az] 

Nella schermata cerco di trovare un ~( , e quindi uso la Depth pila di gruppi denominata per contare le parentesi di apertura estranee.Finché la parentesi si apre in ~( non è mai chiusa, il lookbehind deve corrispondere. è raggiunto, (?...) non può estrarre nulla dallo stack e il lookbehind dovrebbe fallire (cioè, per tutte le lettere da j ). Sfortunatamente, questo non funziona. c , e , f , g e m . Quindi solo questi:

 ~(ab (c) _ (ef (g) _) _) _ (_ (_ (m) _) _) _ 

Ciò sembra significare che il lookbehind non può corrispondere a nulla una volta che ho chiuso una singola parentesi, a meno che non torni al livello di nidificazione più elevato in cui sia mai stato prima.

Ok, questo potrebbe solo significare che c’è qualcosa di strano con la mia espressione regolare, o non ho capito bene i gruppi di bilanciamento. Ma poi ho provato questo senza il lookbehind. Ho creato una stringa per ogni lettera come questa:

 ~(zb (c) d (ef (x) y) g) h (i (j (k) l) m) n ~(az (c) d (ef (x) y) g) h (i (j (k) l) m) n ~(ab (z) d (ef (x) y) g) h (i (j (k) l) m) n .... ~(ab (c) d (ef (x) y) g) h (i (j (k) l) z) n ~(ab (c) d (ef (x) y) g) h (i (j (k) l) m) z 

E ha usato questo modello su ciascuno di questi:

 ~[(](?:[^()]*|(?[(])|(?[)]))*z 

E come desiderato, tutti i casi coincidono, dove z sostituisce una lettera tra i e tutti i casi dopo che falliscono.

Quindi, cosa fa il look-behind (a lunghezza variabile) che rompe questo uso dei gruppi di bilanciamento? Ho provato a cercare questo per tutta la serata (e ho trovato pagine come questa ), ma non sono riuscito a trovare un singolo uso di questo in una schermata.

Sarei anche felice se qualcuno potesse collegarmi ad alcune informazioni approfondite su come il motore regex .NET gestisce internamente le funzionalità specifiche di .NET. Ho trovato questo fantastico articolo , ma non sembra entrare nei lookbehinds (a lunghezza variabile), per esempio.