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