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]
在lookback中,我试图找到一个~(
),然后我使用命名组堆栈Depth
来计算无关的开始括号。只要在~(
中打开的括号从未关闭,lookback就应该匹配。如果到达结束括号,(?)?
~(a b (c) _ (e f (g) _) _) _ (_ (_ (m) _) _) _
这似乎意味着,一旦我关闭了一个括号,lookback就无法匹配任何东西,除非我返回到我以前所去过的最高嵌套级别。
好的,这可能意味着我的正则表达式有点奇怪,或者我没有正确理解平衡组。但后来我在没有人注意的情况下尝试了这个。我为每个字母创建了一个字符串,如下所示:
~(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
之间的字母,之后的所有情况都不匹配。
那么,(可变长度)lookback做了什么,打破了平衡组的使用?我整个晚上都在努力研究这个(并且找到了像这样的页面),但是我在“回头看”中找不到这个的任何用途。
我也很高兴,如果有人能把我和一些关于这个问题的深入信息联系起来。NET正则表达式引擎句柄。NET特定的内部功能。我发现了这篇惊人的文章,但它似乎并没有进入(可变长度)lookbehinds,例如。
我想我明白了。
首先,正如我在其中一个注释中提到的,(?
现在,我们如何让它从左到右捕捉?这非常简单,真的-我们可以使用前瞻来欺骗引擎:
(?<=(?=(?<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
我认为问题出在数据上,而不是模式上。数据具有需要匹配的Post项,例如
(a b(c)d e f)
其中d e和f需要匹配。更平衡的数据将是
(a)b(c)(d)(e)(f))
因此,我对这个示例数据采取的策略要求在大括号后出现赛后情况:
~(a b(c)d(e f(g)h)i)j k
其中j
有趣的是,我对捕获组进行了命名,以找出它们的位置,而j和k在捕获3中出现。我留给你们的不是一个答案,而是一个尝试,看看你们是否能改进它。
(~ # Anchor to a Tilde
( # Note that \x28 is ( and \x29 is )
( # --- PRE ---
(?<Paren>\x28)+ # Push on a match into Paren
((?<Char1>[^\x28\x29])(?:\s?))*
)+ # Represents Sub Group 1
( #---- Closing
((?<Char2>[^\x28\x29])(?:\s?))*
(?<-Paren>\x29)+ # Pop off a match from Paren
)+
(
((?<Char3>[^\x28\x29])(?:\s?))* # Post match possibilities
)+
)+
(?(Paren)(?!)) # Stop after there are not parenthesis
)
下面是我自己创建的一个工具(也许有一天我会发布)的匹配结果。请注意,˽表示空间的匹配位置。
Match #0
[0]: ~(a˽b˽(c)˽d˽(e˽f˽(g)˽h)˽i)˽j˽k
["1"] → [1]: ~(a˽b˽(c)˽d˽(e˽f˽(g)˽h)˽i)˽j˽k
→1 Captures: ~(a˽b˽(c)˽d˽(e˽f˽(g)˽h)˽i)˽j˽k
["2"] → [2]: (e˽f˽(g)˽h)˽i)˽j˽k
→2 Captures: (a˽b˽(c)˽d˽, (e˽f˽(g)˽h)˽i)˽j˽k
["3"] → [3]: (g
→3 Captures: (a˽b˽, (c, (e˽f˽, (g
["4"] → [4]: g
→4 Captures: a˽, b˽, c, e˽, f˽, g
["5"] → [5]: ˽i)
→5 Captures: ), ), ˽h), ˽i)
["6"] → [6]: i
→6 Captures: ˽, h, ˽, i
["7"] → [7]:
→7 Captures: ˽d˽, , ˽j˽k,
["8"] → [8]: k
→8 Captures: ˽, d˽, ˽, j˽, k
["Paren"] → [9]:
["Char1"] → [10]: g
→10 Captures: a, b, c, e, f, g
["Char2"] → [11]: i
→11 Captures: ˽, h, ˽, i
["Char3"] → [12]: k
→12 Captures: ˽, d, ˽, j, k