当前位置: 首页 > 知识库问答 >
问题:

在可变长度lookback中平衡组[重复]

蒲坚
2023-03-14

TL;DR:使用内部捕获(特别是平衡组)。NET的lookbehinds改变了获得的捕获,尽管它不应该有什么不同。这是怎么回事。NET的lookbehinds破坏了预期的行为?

我试图想出另一个问题的答案,作为玩弄的借口。NET的平衡组。然而,我不能让它们在可变长度的后视中工作。

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

考虑这个输入:

~(a b (c) d (e f (g) h) i) j (k (l (m) n) p) q

目标是匹配所有字母,这些字母在括号内,前面是~,不管有多深(所以从ai)。我的尝试是检查在后视中的正确位置,这样我就可以在对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替换ai之间的字母,之后的所有情况都不匹配。

那么,(可变长度)lookback做了什么,打破了平衡组的使用?我整个晚上都在努力研究这个(并且找到了像这样的页面),但是我在“回头看”中找不到这个的任何用途。

我也很高兴,如果有人能把我和一些关于这个问题的深入信息联系起来。NET正则表达式引擎句柄。NET特定的内部功能。我发现了这篇惊人的文章,但它似乎并没有进入(可变长度)lookbehinds,例如。


共有2个答案

柳轶
2023-03-14

我认为问题出在数据上,而不是模式上。数据具有需要匹配的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
龙嘉玉
2023-03-14

我想我明白了。
首先,正如我在其中一个注释中提到的,(?

现在,我们如何让它从左到右捕捉?这非常简单,真的-我们可以使用前瞻来欺骗引擎:

(?<=(?=(?<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

 类似资料:
  • 问题内容: 我如何遍历可变长度的Java数组。 我想我会设置一个while循环,但是如何检测到数组末尾。 我想我想要这样的东西[只需要弄清楚如何表示myArray.notEndofArray()] 问题答案: 要么 第二个版本是“ for-each”循环,它适用于数组和Collections。大多数循环可以使用for- each循环完成,因为您可能并不在乎实际的索引。如果您确实关心实际索引,请使用

  • 问题内容: 即使使用标志,我也无法禁用它。如何禁用它? 问题答案: 您可以使用编译器标志为可变长度数组生成错误:

  • 问题内容: 我想知道如何初始化整数数组,使其大小和值在程序执行过程中发生变化,有什么建议吗? 问题答案: 是的:使用ArrayList。 在Java中,“普通”数组是固定大小的。您必须给它们一个尺寸,并且不能扩展或收缩它们。要更改大小,您必须创建一个新数组并复制所需的数据-这效率低下,给您带来痛苦。 幸运的是,有许多内置类可以实现通用的数据结构以及其他有用的工具。您需要检查Java 6 API的完

  • 问题内容: Core Audio具有C API,可将一些数据复制到您提供的内存中。在一种情况下,我需要传递一个指向AudioBufferList的指针,该指针定义为: UInt32标识缓冲区的数量,并且实际缓冲区紧随其后。 我可以成功获得此: 我无法识别(AudioBuffer)语法,但我认为它并不重要- 我认为括号会被忽略,mBuffers只是一个AudioBuffer,由我自己完成指针数学运算

  • 我想得到一个可变长度数组的前3个元素。我已经整理了我的数组,我想得到一个前3名。 这是我所做的: 我的“解决方案”仅适用于包含4个元素(-1)的数组 有没有更好的方法来使用拼接方法? 谢谢你的帮助

  • 这个问题来自一个很棒的YouTube频道,给出了可以在采访中提出的问题。 它基本上与寻找数组中的平衡点有关。这里有一个例子来最好地解释它;{1,2,9,4,-1}.因为sum(1 ^ 2)= sum(4(-1))使9成为平衡点。在没有检查答案的情况下,我决定先实现这个算法,想问问是否有更有效的方法; < li >对数组O(n)中的所有元素求和 得到总数的一半O(1) < li >从左侧开始扫描数组