TL; DR: Uso cattura (in particolare i gruppi di bilanciamento) all'interno del lookbehinds NET cambia le catture ottenuti, anche se non dovrebbe fare una differenza. Che cosa è con le schermate di .NET che rompono il comportamento previsto?gruppi Balancing a lunghezza variabile lookbehind
Stavo cercando di trovare una risposta a this other question, 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.
Considerate questo ingresso:
~(a b (c) d (e f (g) h) i) j (k (l (m) n) p) q
L'obiettivo è quello di abbinare tutte le lettere, che sono tra parentesi all'interno preceduti da ~
, non importa quanto in profondità (quindi tutto 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 a Matches
. Qui è il mio modello:
(?<=~[(](?:[^()]*|(?<Depth>[(])|(?<-Depth>[)]))*)[a-z]
Nel lookbehind cerco di trovare un ~(
, e poi io uso la pila gruppo denominato Depth
contare parentesi di apertura estranei. Finché la parentesi aperta in ~(
non viene mai chiusa, il lookbehind deve corrispondere. Se la parentesi di chiusura viene raggiunta, lo (?<-Depth>...)
non può estrarre nulla dallo stack e il lookbehind non dovrebbe riuscire (ovvero, per tutte le lettere da j
). Sfortunatamente, questo non funziona. Invece, combacio con a
, b
, c
, e
, f
, g
e m
. Quindi, solo questi:
~(a b (c) _ (e f (g) _) _) _ (_ (_ (m) _) _) _
Questo sembra significare che il lookbehind non può corrispondere nulla una volta che ho chiuso una sola parentesi, a meno che non torno giù al livello di nidificazione più alto Sono stato a prima.
Ok, questo potrebbe significare solo che c'è qualcosa di strano con la mia espressione regolare, o non ho capito correttamente i gruppi di bilanciamento. Ma poi ho provato questo senza il lookbehind. Ho creato una stringa per ogni lettera come questa:
~(z b (c) d (e f (x) y) g) h (i (j (k) l) m) n
~(a z (c) d (e f (x) y) g) h (i (j (k) l) m) n
~(a b (z) d (e f (x) y) g) h (i (j (k) l) m) n
....
~(a b (c) d (e f (x) y) g) h (i (j (k) l) z) n
~(a b (c) d (e f (x) y) g) h (i (j (k) l) m) z
E usato questo modello su ciascuno di questi:
~[(](?:[^()]*|(?<Depth>[(])|(?<-Depth>[)]))*z
E, se lo desideri, tutti i casi match, in cui z
sostituisce una lettera tra a
e i
e tutti i casi successivi falliscono.
Quindi che cosa fa il look-behind (a lunghezza variabile) che interrompe questo uso di gruppi di bilanciamento? Ho provato a cercare questo per tutta la serata (e ho trovato pagine come this one), ma non sono riuscito a trovare un singolo utilizzo 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 this amazing article, ma non sembra entrare nei lookbehinds (a lunghezza variabile), per esempio.
vedi [divertimento con .NET Regex Balancing gruppi] (http://blog.stevenlevithan.com/archivi/gruppi di bilanciamento). – OmegaMan
@OmegaMan, grazie, ma l'ho trovato anche io (in realtà quella era la pagina su cui ho basato il mio codice). Sfortunatamente, anche questo non usa gruppi bilanciati in una schermata. –
quindi, un singolo risultato come "a b (c) d (e f (g) h) i" è accettabile o deve essere 9 corrisponde a, b, c, d, e, f, g, h e i? – Les