【发布时间】: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
【问题讨论】:
模式: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
【问题讨论】:
我不确定是否记录了这种行为(如果是,那么我没有找到),但使用了一个条件构造,包括 一个显式的零宽度断言作为其表达式 @987654322 @ 覆盖 下一个编号 捕获组(清空它)。您可以通过在 RegEx 下方运行来确认这一点:
a(?(?<! ) )b (c)()
解决此问题的四种方法:
将 expression 括在 @DmitryEgorov 所指出的括号中(这也保持第二 完整捕获组)并且不包含在结果中 - 正确 方式:
a(?((?<! )) )b (c)
由于此行为仅适用于未命名的捕获组 (默认)您可以使用命名捕获组获得预期结果:
a(?(?<! ) )b (?<first>c)
在(c) 和条件之间添加一个额外的捕获组:
a(?(?<! ) )(b) (c)
避免这样的表达如果可能。例如:
a(?( ) )b (c)
【讨论】:
a(?( ) )b (c),请注意(?( ) ) 等于(?(?= ) ),而不是(?(?<! ) )(参见Conditional Matching with an Expression。
a(?((?<! )) )b (c)
除了@revo 的answer:
不仅具有显式零宽度断言的条件构造作为其表达式受到影响。 事实上,几乎所有条件表达式都存在的条件结构 使用没有额外括号的带括号的正则表达式(分组、条件、其他特殊)会受到影响。
在这种情况下,有四种(错误)行为:
捕获组数组被破坏(正如 OP 所指出的那样),即 条件构造之后的捕获组丢失 其他组向左移动,最后一个捕获组未定义。
在以下示例中,预期的捕获分配是
$1="a", $2="b", $3="c"
而实际结果是
$1="a", $2="c", $3="" (the latter is empty string)
适用于:
(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) - 带有隐式括号正则表达式的嵌套条件在解析正则表达式时在运行时抛出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"
在模式匹配期间抛出OutOfMemoryException。
据我所知,这显然是一个错误。
适用于:
(a)(?(?i) )(b) (c) - 内联选项(不要与组选项混淆)[令人惊讶地]按预期工作,但这是一个过于人为的例子:
(a)(?(?(.).) )(b) (c) - 带有显式括号正则表达式的嵌套条件所有这些正则表达式都可以通过将条件表达式括在显式括号中来修复(即,如果表达式本身已经包含括号,则额外的)。 以下是固定版本(按出现顺序):
(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
【讨论】: