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

Posted

技术标签:

【中文标题】带有可选匹配组的正则表达式【英文标题】:Regex with optional matching groups 【发布时间】:2016-06-06 22:51:43 【问题描述】:

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

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

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

【问题讨论】:

这是否意味着您的所有部分(包括producercategory)都是可选的? 【参考方案1】:

试试

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

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

【讨论】:

【参考方案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 标志会将所有未命名的捕获组变为 非捕获,因此它们不会出现在 Match.Groups 中.因此,即使不使用非捕获可选组(?:...)?,我们也始终只有 5 个组。

【讨论】:

以上是关于带有可选匹配组的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式匹配

使用正则表达式匹配日志文件行时的可选字段

正则表达式组的绑定可选性而不复制强制性模式部分

[python 学习]正则表达式

获取在正则表达式中匹配的组的索引?

匹配正则表达式中的可选斜杠