C#正则表达式多次返回组

时间:2014-03-03 19:10:33

标签: c# regex

我在C#中有一个非常简单的正则表达式:

(var \= 0\;)

但是当我尝试将此匹配仅出现一次模式的字符串时,我会返回多个组。输入字符串是:

foo bar
var = 0;
foo

我得到了Regex对象返回的1个匹配,但在里面我看到两个组,每个组有1个捕获,这是我想要的字符串。 我需要正则表达式中的分组括号,因为这是更大的正则表达式的一部分,我需要将其作为一个组捕获。 我做错了什么?

修改

这是我使用的C#代码:

private const string REGEX = "(var \\= [0]\\;)";
MatchCollection matches = REGEX.Matches(inputStr);
foreach (Match m in matches)
{
    foreach (Group g in m.Groups)
    {
        Console.WriteLine("group[" + g.Captures.Count + "]: '" + g.ToString() + "'");
    }
}

这就是我得到的:

group[1]: 'var = 0;'
group[1]: 'var = 0;'

我的问题是,为什么我得到两组而不是一组?

编辑#2:

更复杂的模式显示了问题。模式:

# preceding comment
class
{
   (param1 = "val1", param2 = "val2", param3 = val3)
}
[
    # inside comment
    setting1 = 0;
    setting2 = 0;
]

我正在使用的正则表达式:(它可能不是最明显的,但如果要查看它,可以将其粘贴到正则表达式查看器中)

(\#[^\n]*)?(?:[\s\r\n]*)domain(?:[\s\r\n]*)\{(?:[\s\r\n]*)\((?:[\s\r\n]*)(((?:[\s\r\n]*)(accountName(?:[\s\r\n]*)\=(?:[\s\r\n]*)\"[^"]+\"[,]?)(?:[\s\r\n]*))|((?:[\s\r\n]*)(tableName(?:[\s\r\n]*)\=(?:[\s\r\n]*)\"[^"]+\"[,]?)(?:[\s\r\n]*))|((?:[\s\r\n]*)(cap(?:[\s\r\n]*)\=(?:[\s\r\n]*)[\d]+[,]?)(?:[\s\r\n]*))|((?:[\s\r\n]*)(MinPartitionCount(?:[\s\r\n]*)\=(?:[\s\r\n]*)[\d]+[,]?)(?:[\s\r\n]*)))+\)(?:[\s\r\n]*)\}(?:[\s\r\n]*)\[(?:[\s\r\n]*)(\#[^\n]*)?(?:[\s\r\n]*)((?:[\s\r\n]*)(IsSplitEnabled(?:[\s\r\n]*)\=(?:[\s\r\n]*)[0|1](?:[\s\r\n]*)\;)(?:[\s\r\n]*)|(?:[\s\r\n]*)(IsMergeEnabled(?:[\s\r\n]*)\=(?:[\s\r\n]*)[0|1](?:[\s\r\n]*)\;)(?:[\s\r\n]*))*(?:[\s\r\n]*)\]

我得到了:

group:1: '# preceding comment
domain
{
   (param1 = "val1", param2 = "val2", param3 = val3)
}
[
    # inside comment
    setting1 = 0;
    setting2 = 0;
]'
'roup:1: '# preceding comment
group:3: 'cap = 1200'
group:1: 'param1 = "val1", '
group:1: 'param1 = "val1",'
group:1: 'param2 = "val2", '
group:1: 'param2 = "val2",'
group:1: 'param3 = val3'
group:1: 'param3 = val3'
'roup:1: '# inside comment
group:2: 'setting1 = 0;
'
group:1: 'setting1 = 0;'
group:1: 'setting2 = 0;'

1 个答案:

答案 0 :(得分:2)

根据文档,GroupCollection的第一个元素是整个匹配,而不是()创建的第一个组。

从备注部分here底部附近:

  

如果正则表达式引擎可以找到匹配的第一个元素   Groups属性返回的GroupCollection对象包含   与整个正则表达式模式匹配的字符串。 <每个后续元素>如果正则表达式包括捕获组,则表示捕获的组。

因此,根据您当前使用的RegEx,项目0和1都是相同的。要仅查看实际的组匹配,您可以跳过GroupCollection的第一个元素,并仅处理您在RegEx中定义的组。

修改

在调查了其他数据后,我想我可能已经找到了重复的原因。

我相信您看到多个Match,因此外部foreach循环运行两次,而不是一次。这是因为有两条单独的行“= 0;”在示例中。

这是LinqPad示例代码,显示找到2个匹配项,因此输出多个重复组。 (注意,我使用了你提供的简单正则表达式进行测试,因为长正则表达式没有提供任何匹配)

static string inputStr = "# preceding comment \r\n" + 
"class\r\n" + 
"{\r\n" + 
"   (param1 = \"val1\", param2 = \"val2\", param3 = val3)\r\n" + 
"}\r\n" + 
"[\r\n" + 
"    # inside comment\r\n" + 
"    setting1 = 0;\r\n" + 
"    setting2 = 0;\r\n" + 
"]\r\n";

const string REGEX = "(\\= [0]\\;)";

void Main()
{

    var regex = new System.Text.RegularExpressions.Regex(REGEX);
    MatchCollection matches = regex.Matches(inputStr);
    Console.WriteLine("Matches:{0}", matches.Count);
    int matchCnt = 0;
    foreach (Match m in matches)
    {
        int groupCnt = 0;
        foreach (Group g in m.Groups)
        {
            Console.WriteLine("match[{0}] group[{1}]: Captures:{2} '{3}'", matchCnt, groupCnt, g.Captures.Count, g);
            //g.Dump();
            groupCnt++;
        }
        matchCnt++;
    }
    Console.WriteLine("Done!");
}

以下是此代码运行时LinqPad生成的输出:

Matches:2
match[0] group[0]: Captures:1 '= 0;'
match[0] group[1]: Captures:1 '= 0;'
match[1] group[0]: Captures:1 '= 0;'
match[1] group[1]: Captures:1 '= 0;'
Done!