如何避免第一组捕获被省略?

编程语言 2026-07-10

我在.NET 8中创建了一个模式,用来在字符串中仅匹配并捕获两个命名分组。我使用起始和结束字符串锚点来匹配整个字符串。然而,它也会在第二行只匹配并捕获第二个命名分组,我不知道该如何避免。请帮我解决这个问题。

这是我的正则表达式模式:

^\s+(?<CODE>[X][B|M]\d{6}[A-Z]|[a-z]?)\s+(?<NAME>.+)$

这会匹配下方所示的第一行,并捕获我需要的两个分组,但在第二行时也会仅匹配并捕获第二个命名分组。我认为这与 .+ 有关,但我不知道如何修复。在 <CODE> 分组之后,字符串通常包含若干空格,之后是任意组合的数字、字符和空格,一直到字符串末尾。

我想确保先捕获第一个命名分组,再捕获第二个命名分组。

  XM204000B    200 SUNSHINE RD  & PALACE
  FOB     NUMBER

解决方案

在你的正则表达式中,这一部分 [X][B|M]X[BM] 相同,因为这里的管道符号 | 被用于一个 字符类 中,并且是字面量匹配。X 可以不用方括号来书写。

在正则的这一部分,竖线表示一种分支(alternation),正如在 分组 中的用法:

(?<CODE>[X][B|M]\d{6}[A-Z]|[a-z]?)
                          ^

因此它匹配 [X][B|M]\d{6}[A-Z][a-z]? 中的任意一个,其中问号使 [a-z] 部分成为可选。

由于现在是可选的,你可以在第二个示例字符串的截图中看到,CODE 组可能得到一个空匹配:

在此输入图片描述

你更新后的正则看起来会是这样,使用一个单一的可选字符类 [A-Za-z]?

^\s+(?<CODE>X[BM]\d{6}[A-Za-z]?)\s+(?<NAME>.+)$

请参阅 regex 101演示

  • 对于 NAME 组,你使用 .+,其中 '.' 也可能只匹配空格,这对匹配名字可能并非你想要的。
  • 使用 \s 匹配一个空白字符,这也可能匹配换行符。

如果你不想匹配换行符,并且名字应至少以一个非空白字符开头,你可以把正则写成:

^[\p{Zs}\t]+(?<CODE>X[BM]\d{6}[A-Za-z]?)[\p{Zs}\t]+(?<NAME>\S.*)$

该正则匹配:

  • ^ 字符串起始位置
  • [\p{Zs}\t]+ 匹配一个或多个水平空白字符
  • (?<CODE> 命名捕获组 CODE
  • X[BM]\d{6} 匹配 X,随后是 BM,以及6 位数字
  • [A-Za-z]? 匹配一个可选的A-Z或 a-z字符
  • ) 关闭该分组
  • [\p{Zs}\t]+ 匹配一个或多个水平空白字符
  • (?<NAME> 命名捕获组 NAME
  • \S.* 匹配一个单个非空白字符,随后是任意数量的非换行符字符
  • ) 关闭该分组
  • $ 字符串结尾

请参阅 regex 101演示

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章