带有可选匹配组的正则表达式

Regex with optional matching groups

我正在尝试解析给定的字符串,它是一种用 / 分隔的路径。我需要编写正则表达式来匹配路径中的每个段到相应的正则表达式组。

示例 1:

输入:

/EAN/SomeBrand/appliances/refrigerators/RF444

输出:

Group: producer, Value: SomeBrand Group: category, Value: appliances Group: subcategory, Value: refrigerators Group: product, Value: RF4441

示例 2:

输入:

/EAN/SomeBrand/appliances

输出:

Group: producer, Value: SomeBrand Group: category, Value: appliances Group: subcategory, Value: Group: product, Value:

我尝试了以下代码,当路径已满(如第一个示例)时它工作正常,但当输入字符串是独立的(如示例 2)时无法找到组。

static void Main()
{
  var pattern = @"^" + @"/EAN"
                + @"/" + @"(?<producer>.+)"
                + @"/" + @"(?<category>.+)"
                + @"/" + @"(?<subcategory>.+)"
                + @"/" + @"(?<product>.+)?"
                + @"$";

  var rgx = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
  var result = rgx.Match(@"/EAN/SomeBrand/appliances/refrigerators/RF444");

  foreach (string groupName in rgx.GetGroupNames())
  {
    Console.WriteLine(
       "Group: {0}, Value: {1}",
       groupName,
       result.Groups[groupName].Value);
  }


  Console.ReadLine();
}

欢迎任何建议。不幸的是,我不能简单地拆分字符串,因为我使用的框架需要正则表达式对象。

您可以使用可选组 (...)? 并将 .+ 贪心点匹配模式替换为否定字符 类 [^/]+:

^/EAN/(?<producer>[^/]+)/(?<category>[^/]+)(/(?<subcategory>[^/]+))?(/(?<product>[^/]+))?$
                                           ^                      ^^^                  ^^

regex demo

这是您需要在 C# 代码中声明正则表达式的方式:

var pattern = @"^" + @"/EAN"
            + @"/(?<producer>[^/]+)"
            + @"/(?<category>[^/]+)"
            + @"(/(?<subcategory>[^/]+))?"
            + @"(/(?<product>[^/]+))?"
            + @"$";

var rgx = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);

请注意,我使用常规捕获组作为可选组,但是 RegexOptions.ExplicitCapture 标志将所有未命名的捕获组变为 非捕获,因此,它们确实如此没有出现在 Match.Groups 当中。因此,即使不使用非捕获可选组,我们也始终只有 5 个组 (?:...)?.

尝试

var pattern = @"^" + @"/EAN"
    + @"(?:/" + @"(?<producer>[^/]+))?"
    + @"(?:/" + @"(?<category>[^/]+))?"
    + @"(?:/" + @"(?<subcategory>[^/]+))?"
    + @"(?:/" + @"(?<product>[^/]+))?";

请注意我是如何用 [^/] 替换 . 的,因为您想使用 / 来拆分字符串。请注意每个子部分甚至使用可选量词 (?)