.NET正则表达式不按预期顺序捕获

Din*_*nah 5 .net regex

在.NET中,正则表达式并没有像我期望的那样组织捕获.(我不会称这是一个错误,因为显然有人打算这样做.但是,这不是我期望它工作的方式,也不是我觉得它有用.)

这个正则表达式用于配方成分(为了举例简化):

(?<measurement>           # begin group
  \s*                     # optional beginning space or group separator
  (
    (?<integer>\d+)|      # integer
    (
      (?<numtor>\d+)      # numerator
      /
      (?<dentor>[1-9]\d*) # denominator. 0 not allowed
    )
  )
  \s(?<unit>[a-zA-Z]+)
)+                        # end group. can have multiple
Run Code Online (Sandbox Code Playgroud)

我的字符串: 3 tbsp 1/2 tsp

结果组和捕获:

[测量] [0] = 3汤匙
[测量] [ 1 ] = 1/2茶匙
[整数] [0] = 3
[numtor] [ 0 ] = 1
[dentor] [ 0 ] = 2
[unit] [0] = tbsp
[unit] [ 1 ] = tsp

请注意,即使1/2 tsp在第二次捕获中,它的部分也在,[0]因为这些斑点以前未使用过.

有没有办法让所有部分都具有可预测的有用索引,而无需再次通过正则表达式重新运行每个组?

Ala*_*ore 1

有没有什么方法可以让所有部分都具有可预测的有用索引,而不必再次通过正则表达式重新运行每个组?

不适用于捕获。如果您无论如何都要执行多个匹配,我建议您删除+并分别匹配测量的每个组件,如下所示:

  string s = @"3 tbsp 1/2 tsp";

  Regex r = new Regex(@"\G\s* # anchor to end of previous match
    (?<measurement>           # begin group
      (
        (?<integer>\d+)       # integer
      |
        (
          (?<numtor>\d+)      # numerator
          /
          (?<dentor>[1-9]\d*) # denominator. 0 not allowed
        )
      )
      \s+(?<unit>[a-zA-Z]+)
    )                         # end group.
  ", RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture);

  foreach (Match m in r.Matches(s))
  {
    for (int i = 1; i < m.Groups.Count; i++)
    {
      Group g = m.Groups[i];
      if (g.Success)
      {
        Console.WriteLine("[{0}] = {1}", r.GroupNameFromNumber(i), g.Value);
      }
    }
    Console.WriteLine("");
  }
Run Code Online (Sandbox Code Playgroud)

输出:

[measurement] = 3 tbsp
[integer] = 3
[unit] = tbsp

[measurement] = 1/2 tsp
[numtor] = 1
[dentor] = 2
[unit] = tsp
Run Code Online (Sandbox Code Playgroud)

开头的at\G确保匹配仅发生在上一个匹配结束的位置(或者如果这是第一次匹配尝试,则发生在输入的开头)。您还可以保存调用之间的匹配结束位置,然后使用双参数Matches方法在同一点恢复解析(就好像那确实是输入的开始)。