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

时间:2016-02-24 15:04:22

标签: c# regex regex-group

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

示例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();
}

欢迎任何建议。不幸的是,我不能简单地拆分字符串,因为我使用的框架是预期的regex对象。

2 个答案:

答案 0 :(得分:2)

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

^/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标志将所有未命名的捕获组转换为非捕获,因此它们不会出现在{ {1}}。因此,即使不使用非捕获可选组Match.Groups,我们也始终只有5个组。

答案 1 :(得分:1)

尝试

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

请注意我如何将.替换为[^/],因为您想使用/来分割字符串。请注意甚至为每个子部分(?

使用可选的量词