TL;DR:在 .NET 的lookbehinds 中使用捕获(特别是平衡组)会改变获得的捕获,尽管它不应该产生影响。.NET 的lookbehinds 是什么破坏了预期的行为?
我试图想出对另一个问题的答案,以此作为玩弄 .NET 平衡组的借口。但是,我无法让它们在可变长度的后视中工作。
首先,请注意,我不打算有效地使用这个特定的解决方案。这更多是出于学术原因,因为我觉得可变长度后视发生了一些我不知道的事情。并且知道将来当我实际上需要使用这样的东西来解决问题时,它可能会派上用场。
考虑这个输入:
~(a b (c) d (e f (g) h) i) j (k (l (m) n) p) q
目标是匹配所有字母,这些字母在括号内,前面有~
,不管有多深(所以从a
到i
)。我的尝试是在后视中检查正确的位置,以便我可以在一次调用中获取所有字母Matches
。这是我的模式:
(?<=~[(](?:[^()]*|(?<Depth>[(])|(?<-Depth>[)]))*)[a-z]
在后视中,我尝试找到一个~(
,然后我使用命名的组堆栈Depth
来计算无关的左括号。只要在其中打开的括号~(
从未关闭,则向后查找应该匹配。如果到达了右括号,(?<-Depth>...)
则无法从堆栈中弹出任何内容,并且后向查找应该失败(即,对于来自 的所有字母j
)。不幸的是,这不起作用。相反,我匹配a
, b
, c
, e
, f
,g
和m
. 所以只有这些:
~(a b (c) _ (e f (g) _) _) _ (_ (_ (m) _) _) _
这似乎意味着一旦我关闭了一个括号,lookbehind 就无法匹配任何东西,除非我回到我之前去过的最高嵌套级别。
好的,这可能只是意味着我的正则表达式有些奇怪,或者我没有正确理解平衡组。但后来我尝试了这个,没有向后看。我为每个字母创建了一个字符串,如下所示:
~(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
并在其中的每一个上使用了这种模式:
~[(](?:[^()]*|(?<Depth>[(])|(?<-Depth>[)]))*z
并且根据需要,所有案例都匹配,其中替换和之后的所有案例z
之间的一个字母失败。a
i
那么(可变长度)lookbehind 做了什么打破了平衡组的这种使用?我整个晚上都试图研究这个(并找到了像这样的页面),但我在回顾中找不到这个的单一用途。
如果有人可以将我链接到有关 .NET 正则表达式引擎如何在内部处理 .NET 特定功能的一些深入信息,我也会很高兴。我发现了这篇很棒的文章,但它似乎并没有进入(可变长度)lookbehinds,例如。