具有条件lookbehind和捕获组的.net正则表达式

时间:2016-08-17 07:58:29

标签: .net regex

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

输入:a b c

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

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

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

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

2 个答案:

答案 0 :(得分:4)

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

(?(?=expression)yes|no)

克服此问题的四种方法:

  1. 表达式括在@DmitryEgorov指出的括号中(同时保留第二个) 捕获组完整)并且不包括在结果中 - 右边 方式:

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

    a(?((?<! )) )b (c)
    
  3. a(?(?<! ) )b (?<first>c) 和条件:

    之间随意添加额外的捕获组
    (c)
  4. 如果可能,避免使用这样的表达。 E.g:

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

答案 1 :(得分:2)

除了@ revo&#39; s answer

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

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

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

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

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

    而实际结果是

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

    适用于:

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

    适用于:

    • (a)(?(?<n>.) )(b) (c)(a)(?(?'n'.) )(b) (c) - 已命名的群组 - 例外消息:"Alternation conditions do not capture and cannot be named"
    • (a)(?(?'-n' .) )(b) (c)(?<a>a)(?(?<a-n>.) )(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. [令人惊讶]按预期工作,但这是一个太人为的例子:

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

    (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