正则表达式分组问题

时间:2009-05-13 18:20:05

标签: regex

我有一些这种格式的文字数据:

MI
00
3

MD
1
0.0000
MD
2
0.0000
MD
3
0.0000

可以重复此块,并且MD的数量是可变的(但总是> = 1),并且需要为每个块捕获以下数值。

我有一个匹配每个MI的每个MD的正则表达式,但它只捕获最后一个MD。是否有可能在不事先知道有多少MD的情况下捕获每个MD?

编辑:根据请求... 正则表达式在下面;我的问题的重要部分仍然是“我可以捕获每一个MD集吗?”

MI\r\d\d\r(\d)\r[\s\w]{6}\r(MD\r[\s\d]{2}\r[\s\d\.\-]*\r)+

我选择的语言是C#,但我会用任何语言回答,因为它至少会给我一个开始。

MD是从90年代初开始的硫检测器中的数据点。

5 个答案:

答案 0 :(得分:3)

每个Match都有一个Groups集合。在您的情况下,匹配[0] .Groups [1]将匹配MD记录,如“MD \ n1 \ n0.0000MD \ n2 \ n0.0000MD \ n3 \ n0.0000”。

每个组都有Captures collection,您可以迭代查找所有MD实例。这将为每个MD提供一个字符串,因此Matches [0] .Groups [1] .Captures [0]将为“MD \ n1 \ n0.0000”。

编辑:虽然您已经接受了答案,但这是一种解决所有问题的方法:

string pat = @"MI[\r\n]*(?<MI1>\d\d)[\r\n]*(?<MI2>\d+)[\r\n]*" +
    @"(MD[\r\n]*(?<MD1>\d+)*[\r\n]*(?<MD2>[\d\.\-]+)+[\r\n]*)*";

var r = new Regex(pat);
foreach (Match match in r.Matches(text))
{
    Console.WriteLine("MI v1:{0} v2:{1}", 
         match.Groups["MI1"], match.Groups["MI2"]);

    if (match.Groups.Count > 2)
        for (var i = 0; i < match.Groups["MD1"].Captures.Count; i++)
            Console.WriteLine("  MD v1:{0} v2:{1}", 
                match.Groups["MD1"].Captures[i], 
                match.Groups["MD2"].Captures[i]);
}

这是我使用的测试文本:

MI
00
3

MD
1
0.1000
MD
2
0.2000
MD
3
0.3000

MI
12
5

MI
24
5

MD
1
0.1000

输出结果为:

MI v1:00 v2:3
  MD v1:1 v2:0.1000
  MD v1:2 v2:0.2000
  MD v1:3 v2:0.3000
MI v1:12 v2:5
MI v1:24 v2:5
  MD v1:1 v2:0.1000

答案 1 :(得分:2)

这是可能的,但它需要不止一次通过数据。正则表达式组每次匹配只能容纳一个信息块。因此,您可以拥有一个MD组并查找所有MD匹配或一个包含MD组的MI组,并且可以找到所有MI匹配...但MD组不会被分离出来。

一种解决方案是嵌套的正则表达式调用,第一个解决方案是找到每个MI组,第二个解决方案是找到MI组中的每个MD组。

答案 2 :(得分:0)

我认为这样做会。至少它可以使用Perl与RegexBuddy一起使用。

MD[^MI]*

数据刚从上面重复。

编辑: 这似乎捕获了所有MD和初始MI在它自己的小块中。

MI([^MI]*(MD[^MI]*)*)

答案 3 :(得分:0)

我不是C#的专家,但在Java中,你想要改变(MD ...)+到((MD ...)+)。这样,您可以使用外部括号来捕获所有MD。

答案 4 :(得分:0)

我建议您为此任务实施state machine ..

但这是一个正则表达式,我认为也会有效:

MI\r\d\d\r(\d)\r\r(MD\r\d\r[0-9\.]+\r?)*