正则表达式交替构造吃掉前一组的一部分

时间:2013-12-01 16:32:46

标签: c# regex

我正试图制作一个正则表达式来捕获一个函数样式参数列表,它应该是直截了当的,但是我遇到了一个我不理解的行为。

在下面的代码片段中,第一个示例的行为正如您所期望的那样,将函数名称捕获到第一个组中,将参数列表捕获到第二个组中。

在第二个例子中,我想用'一个或多个'量词替换用于捕获参数列表的'零个或多个'量词,这样如果没有参数,第二个组将失败。我期待正则表达式只捕获函数名称,但由于某种原因,正则表达式正在使用函数名称末尾的'1',我不能为我的生活看到为什么会这样做。请问有谁能看到这个问题吗?

// {func1} {blah, blah, blah}
Match m13 = Regex.Match("func1(blah, blah, blah)", @"(\w+) (?([(]) [(]([^)]*) )",
    RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);

// {func}
Match m14 = Regex.Match("func1()", @"(\w+) (?([(]) [(]([^)]+) )",
    RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);

1 个答案:

答案 0 :(得分:1)

您的表情可以调整为:

(\w+) (?([(]) [(]([^)]*) )
                      ^ rather than +

表达式返回意外结果的原因与回溯有关。正则表达式引擎有效地采取以下步骤:

  1. (\w)匹配func1
  2. func1后面紧跟一个(,匹配条件匹配结构中的零宽度表达式。
  3. 条件构造需要(字面值,后跟一个或多个不是)的字符。 此条件因输入func1()而失败,因为()之间的字符为零。
  4. 引擎回溯到步骤(1)并删除字符,以便(\w)现在匹配func而不是func1
  5. func后面紧跟一个1,它不满足条件匹配结构中的零宽度表达式。
  6. 由于条件匹配构造不匹配且没有替代表达式,因此正则表达式在第一个捕获的组中成功完成func,而在第二个捕获的组中没有匹配。
  7. 问题出现在第3步中,其中表达式无法允许()作为合法参数列表。调整表达式以允许在开括号和右括号之间使用零字符(如上所示)允许此序列。诸如^(\w+)(?:\((.*)\))?$之类的表达式也可以在不需要条件构造的情况下解决潜在问题。