与非捕获组在C#中的正则表达式与非、正则表达式

2023-09-03 17:42:33 作者:╯悲哀的现实

我用下面的正则表达式

JOINTS.*\s*(?:(\d*\s*\S*\s*\S*\s*\S*)\r\n\s*)*

对下列类型的数据:

on the following type of data:

 JOINTS               DISPL.-X               DISPL.-Y               ROTATION


     1            0.000000E+00           0.975415E+01           0.616921E+01
     2            0.000000E+00           0.000000E+00           0.000000E+00

我们的想法是,提取两组,每组包含一个线路(从联合编号,1,2,等)中的C#code是如下:

The idea is to extract two groups, each containing a line (starting with the Joint Number, 1, 2, etc.) The C# code is as follows:

string jointPattern = @"JOINTS.*\s*(?:(\d*\s*\S*\s*\S*\s*\S*)\r\n\s*)*";
MatchCollection mc = Regex.Matches(outFileSection, jointPattern );
foreach (Capture c in mc[0].Captures)
{
    JointOutput j = new JointOutput();
    string[] vals = c.Value.Split();
    j.Joint = int.Parse(vals[0]) - 1;
    j.XDisplacement = float.Parse(vals[1]);
    j.YDisplacement = float.Parse(vals[2]);
    j.Rotation = float.Parse(vals[3]);
    joints.Add(j);
}

不过,这并不工作:​​而不是返回2捕获组(内部组),它返回一个组:整个块​​,包括列标题。为什么会出现这种情况?是否有未捕获组C#处理不同?

However, this does not work: rather than returning two captured groups (the inside group), it returns one group: the entire block, including the column headers. Why does this happen? Does C# deal with un-captured groups differently?

最后,是正则表达式来做到这一点的最好方法是什么? (我真的不觉得我有两个问题了。)

Finally, are RegExes the best way to do this? (I really do feel like I have two problems now.)

推荐答案

MC [0] .Captures 等同于 MC [0]。组[0] .Captures 组[0] 总是指的是整场比赛,所以将永远只能是与此相关的一个捕捉。你要找的那部分被捕获组#1,所以你应该使用 MC [0] .Groups [1] .Captures

mc[0].Captures is equivalent to mc[0].Groups[0].Captures. Groups[0] always refers to the whole match, so there will only ever be the one Capture associated with it. The part you're looking for is captured in group #1, so you should be using mc[0].Groups[1].Captures.

但你的正则表达式的目的是匹配整个输入一次尝试,所以匹配()方法总是返回一个MatchCollection只有一个匹配它(假设匹配成功)。你还不如用匹配()来代替:

But your regex is designed to match the whole input in one attempt, so the Matches() method will always return a MatchCollection with only one Match in it (assuming the match is successful). You might as well use Match() instead:

  Match m = Regex.Match(source, jointPattern);
  if (m.Success)
  {
    foreach (Capture c in m.Groups[1].Captures)
    {
      Console.WriteLine(c.Value);
    }
  }

输出:

1            0.000000E+00           0.975415E+01           0.616921E+01
2            0.000000E+00           0.000000E+00           0.000000E+00