正则表达式 - 捕获重复组

时间:2011-05-12 18:14:23

标签: .net regex c#-4.0

好吧,我已经阅读了tutorials,并且为了能够清楚地看清楚我的头脑太乱了。

我正在尝试从函数签名中捕获参数及其类型信息。所以给出这样的签名:

function(/*string*/a,b,c)

我想得到这样的部分:

type: string
param:a
param:b
param:c

这也是好的:

type: string
param:a
type: null (or whitespace)
param:b
type: null (or whitespace)
param:c

所以我提出了这个正则表达式,它正在做重复捕获的常见错误(我明确捕获已开启):

function\(((\/\*(?<type>[a-zA-Z]+)\*\/)?(?<param>[0-9a-zA-Z_$]+),?)*\)
问题是,我无法纠正错误。 :(。请帮忙!

3 个答案:

答案 0 :(得分:3)

通常,您需要两个步骤来获取所有数据 首先,匹配/验证整个功能:

function\((?<parameters>((\/\*[a-zA-Z]+\*\/)?[0-9a-zA-Z_$]+,?)*)\)

请注意,现在您拥有一个包含所有参数的parameters组。您可以再次匹配某些模式以获取所有参数匹配,或者在这种情况下,在,上进行拆分。

如果你正在使用.Net,那么你很幸运。 .Net保存每个组的所有捕获的完整记录,因此您可以使用该集合:

match.Groups["param"].Captures

一些注意事项:

  • 如果您确实要捕获多种类型,肯定需要空匹配,这样您就可以轻松组合匹配(虽然您可以排序,但是1对1捕获更整洁)。在这种情况下,您希望在已捕获的组中选择 组:(?<type>(\/\*[a-zA-Z]+\*\/)?)
  • 您不必以.Net模式转义斜杠 - /没有特殊含义(C#/。Net没有正则表达式分隔符)。

以下是使用捕获的示例。同样,重点是保持typeparam之间的关系:你想要捕获空类型,这样你就不会丢失数量。
图案:

function
\(
(?:
    (?:
        /\*(?<type>[a-zA-Z]+)\*/    # type within /* */
        |                           # or
        (?<type>)                   # capture an empty type.
    )
    (?<param>
        [0-9a-zA-Z_$]+
    )
    (?:,|(?=\s*\)))     # mandatory comma, unless before the last ')'
)*
\)

代码:

Match match = Regex.Match(s, pattern, RegexOptions.IgnorePatternWhitespace);
CaptureCollection types = match.Groups["type"].Captures;
CaptureCollection parameters = match.Groups["param"].Captures;
for (int i = 0; i < parameters.Count; i++)
{
    string parameter = parameters[i].Value;
    string type = types[i].Value;
    if (String.IsNullOrEmpty(type))
        type = "NO TYPE";
    Console.WriteLine("Parameter: {0}, Type: {1}", parameter, type);
}

答案 1 :(得分:1)

您引用的页面使用?:进行非捕获,然后围绕其自己的组中的重复捕获。我猜他们在暗示这样的事情function\(((?:(\/\*(?<type>[a-zA-Z]+)\*\/)?(?<param>[0-9a-zA-Z_$]+),?)*)\)

我喜欢使用http://gskinner.com/RegExr/来测试我的表达式,但它不会显示重复捕获。您可能必须在返回的任何返回结构中循环遍历结果,以查看其他非.NET语言中的值。

抱歉,我无法更加彻底地测试......

答案 2 :(得分:1)

由于这个问题很活跃,已经有一段时间了,但我想我终于找到了答案。

我认为我一直在寻找与你相同的情况,但是对于PHP的使用,并且在另一篇文章中有一个答案,我发现使用\K\G命令工作得很好来自PCRE。请参阅Alan Moore的回答:PHP Regular Expression - Repeating Match of a Group

我的问题是尝试提取表格中的所有单元格值,其中每行包含6位数字,20x 1位或2位数字,以及不相关的1位或2位数字。解决方案是:

<tr class="[^"]*">\s+<td>(\d{6})<\/td>|\G<\/td>[^<>]*+<td>\K\d{1,6}|<td>(\d{1,2})<\/td>

非常好的解决方案,如果我自己这样说的话!