gpt4 book ai didi

.net - 可变长度后视中的平衡组

转载 作者:行者123 更新时间:2023-12-03 22:23:50 27 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Why does this backreference not work inside a lookbehind?

(1 个回答)


5年前关闭。




TL;DR: Using capturing (and in particular balancing groups) inside .NET's lookbehinds changes the obtained captures, although it shouldn't make a difference. What is it with .NET's lookbehinds that breaks the expected behavior?



我试图想出一个答案 this other question ,作为玩弄 .NET 平衡组的借口。但是,我无法让它们在可变长度的lookbehind 中工作。

首先,请注意我不打算有效地使用这个特定的解决方案。这更多是出于学术原因,因为我觉得可变长度后视发生了一些我不知道的事情。并且知道这在将来会派上用场,当我实际上需要使用这样的东西来解决问题时。

考虑这个输入:
~(a b (c) d (e f (g) h) i) j (k (l (m) n) p) q

目标是匹配括号内的所有字母,这些字母以 ~ 开头。 ,不管有多深(所以从 ai 的所有内容)。我的尝试是在后视中检查正确的位置,这样我就可以在一次调用 Matches 中获得所有字母。 .这是我的模式:
(?<=~[(](?:[^()]*|(?<Depth>[(])|(?<-Depth>[)]))*)[a-z]

在回顾中,我试图找到一个 ~( ,然后我使用命名组堆栈 Depth计算无关的左括号。只要括号在 ~(中打开永远不会关闭,后视应该匹配。如果到达那个的右括号, (?<-Depth>...)无法从堆栈中弹出任何内容,并且后视应该失败(即,对于来自 j 的所有字母)。不幸的是,这不起作用。相反,我匹配 a , b , c , e , f , gm .所以只有这些:
~(a b (c) _ (e f (g) _) _) _ (_ (_ (m) _) _) _

这似乎意味着一旦我关闭了一个括号,后视就无法匹配任何东西, 除非 我回到我以前去过的最高嵌套级别。

好的,这可能只是意味着我的正则表达式有些奇怪,或者我没有正确理解平衡组。但是后来我在没有后视的情况下尝试了这个。我为每个字母创建了一个字符串,如下所示:
~(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 做了什么破坏了平衡组的这种使用?我整个晚上都试图研究这个(并找到了类似 this one 的页面),但我在回顾中找不到它的单一用途。

如果有人可以将我链接到有关 .NET 正则表达式引擎如何在内部处理 .NET 特定功能的一些深入信息,我也会很高兴。我找到了 this amazing article ,但它似乎没有进入(可变长度)lookbehinds,例如。

最佳答案

我想我明白了。
首先,正如我在其中一条评论中提到的,(?<=(?<A>.)(?<-A>.))从不匹配。
但后来我想, (?<=(?<-A>.)(?<A>.)) 怎么样? ?它确实匹配!
怎么样(?<=(?<A>.)(?<A>.)) ?与 "12" 匹配, A是捕获 "1" ,如果我们看看 Captures收藏,是{"2", "1"} - 前两个,然后一个 - 反过来。
因此,在lookbehind中,.net从右到左匹配和捕获 .

现在,我们怎样才能让它从左到右捕捉?这很简单,真的 - 我们可以使用前瞻来欺骗引擎:

(?<=(?=(?<A>.)(?<A>.))..)

应用于您的原始模式,我想出的最简单的选择是:
(?<=
~[(]
(?=
(?:
[^()]
|
(?<Depth>[(])
|
(?<-Depth>[)])
)*
(?<=(\k<Prefix>)) # Make sure we matched until the current position
)
(?<Prefix>.*) # This is captured BEFORE getting to the lookahead
)
[a-z]

这里的挑战是现在平衡部分可能会在任何地方结束,所以我们让它一直到达当前位置(像 \G\Z 这样的东西在这里会很有用,但我不认为 .net 有那个)

这种行为很可能记录在某处,我会尝试查找。

这是另一种方法。这个想法很简单 - .net 想要从右到左匹配?美好的!拿着它:
(提示: 从底部开始阅读 - 这就是 .net 的做法)
(?<=
(?(Depth)(?!)) # 4. Finally, make sure there are no extra closed parentheses.
~\(
(?> # (non backtracking)
[^()] # 3. Allow any other character
|
\( (?<-Depth>)? # 2. When seeing an open paren, decreace depth.
# Also allow excess parentheses: '~((((((a' is OK.
|
(?<Depth> \) ) # 1. When seeing a closed paren, add to depth.
)*
)
\w # Match your letter

关于.net - 可变长度后视中的平衡组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13389560/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com