【问题标题】:.net regex with condition lookbehind and capture group.net 正则表达式,带有条件后视和捕获组
【发布时间】:2016-12-23 18:49:37
【问题描述】:

模式:a(?(?<! ) )b (c)

输入:a b c

描述:条件应该匹配空格,如果lookbehind不是空格。

匹配正确,但捕获组 $1 为空(不包含 c)。

这是 .net 正则表达式的问题还是我遗漏了什么?

示例:http://regexstorm.net/tester?p=a(%3f(%3f%3C!+)+)b+(c)&i=a+b+c

【问题讨论】:

    标签: .net regex


    【解决方案1】:

    我不确定是否记录了这种行为(如果是,那么我没有找到),但使用了一个条件构造,包括 一个显式的零宽度断言作为其表达式 @987654322 @ 覆盖 下一个编号 捕获组(清空它)。您可以通过在 RegEx 下方运行来确认这一点:

    a(?(?<! ) )b (c)()
    

    解决此问题的四种方法:

    1. expression 括在 @DmitryEgorov 所指出的括号中(这也保持第二 完整捕获组)并且不包含在结果中 - 正确 方式:

      a(?((?<! )) )b (c)
      
    2. 由于此行为仅适用于未命名的捕获组 (默认)您可以使用命名捕获组获得预期结果:

      a(?(?<! ) )b (?<first>c)
      
    3. (c) 和条件之间添加一个额外的捕获组:

      a(?(?<! ) )(b) (c)
      
    4. 避免这样的表达如果可能。例如:

      a(?( ) )b (c)
      

    【讨论】:

    • 关于a(?( ) )b (c),请注意(?( ) ) 等于(?(?= ) ),而不是(?(?&lt;! ) )(参见Conditional Matching with an Expression
    • 是的,添加了正确的短语。 @WiktorStribiżew
    • 解决此问题的另一种方法是将条件包含在一个额外的捕获组中:a(?((?&lt;! )) )b (c)
    • 我认为在 .NET 正则表达式风格中进行条件测试的正确语法是这样的。我会添加它。 @DmitryEgorov
    • 令人着迷!似乎只有当括号执行双重任务时才会出现问题:包含条件表达式并在表达式中形成组构造的一部分。这对我来说似乎是一个错误。
    【解决方案2】:

    除了@revo 的answer

    不仅具有显式零宽度断言的条件构造作为其表达式受到影响。 事实上,几乎所有条件表达式都存在的条件结构 使用没有额外括号的带括号的正则表达式(分组、条件、其他特殊)会受到影响。

    在这种情况下,有四种(错误)行为:

    1. 捕获组数组被破坏(正如 OP 所指出的那样),即 条件构造之后的捕获组丢失 其他组向左移动,最后一个捕获组未定义。

      在以下示例中,预期的捕获分配是

      $1="a", $2="b", $3="c"
      

      而实际结果是

      $1="a", $2="c", $3="" (the latter is empty string)
      

      适用于:

    2. 在解析正则表达式时在运行时抛出ArgumentException。这实际上是有道理的,因为这明确地警告我们一些潜在的正则表达式错误,而不是像之前的情况那样在捕获中玩有趣的把戏。

      适用于:

      • (a)(?(?&lt;n&gt;.) )(b) (c), (a)(?(?'n'.) )(b) (c) - 命名组 - 异常消息:"Alternation conditions do not capture and cannot be named"
      • (a)(?(?'-n' .) )(b) (c), (?&lt;a&gt;a)(?(?&lt;a-n&gt;.) )(b) (c) - 平衡组 - 异常消息:"Alternation conditions do not capture and cannot be named"
      • (a)(?(?# comment) )(b) (c) - 内联注释 - 异常消息:"Alternation conditions cannot be comments"
    3. 在模式匹配期间抛出OutOfMemoryException。 据我所知,这显然是一个错误。

      适用于:

      • (a)(?(?i) )(b) (c) - 内联选项(不要与组选项混淆)
    4. [令人惊讶地]按预期工作,但这是一个过于人为的例子:

    所有这些正则表达式都可以通过将条件表达式括在显式括号中来修复(即,如果表达式本身已经包含括号,则额外的)。 以下是固定版本(按出现顺序):

    (a)(?((?=.)) )(b) (c)
    (a)(?((?!z)) )(b) (c)
    (a)(?((?<=.)) )(b) (c)
    (a)(?((?<! )) )(b) (c)
    (a)(?((?: )) )(b) (c)
    (a)(?((?i:.)) )(b) (c)
    (a)(?((?>.)) )(b) (c)
    (a)(?((?(1).)) )(b) (c)
    ((?<n>a))(?((?(n).)) )(b)(c)
    (a)(?((?(?:.).)) )(b) (c)
    (a)(?((?<n>.)) )(b) (c)
    (a)(?((?'n'.)) )(b) (c)
    (a)(?((?'-n' .)) )(b) (c)
    (?<a>a)(?((?<a-n>.)) )(b) (c)
    (a)(?((?# comment)) )(b) (c)
    (a)(?((?i)) )(b) (c)
    (a)(?((?(.).)) )(b) (c)
    

    检查所有这些表达式的示例代码:https://ideone.com/KHbqMI

    【讨论】:

    • 很好的探索。
    猜你喜欢
    • 2015-08-20
    • 1970-01-01
    • 2013-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 2014-09-23
    相关资源
    最近更新 更多