Skip to main content
 首页 » 编程设计

c#之正则表达式可选部分中的捕获组

2024年01月26日28bluestorm

我想在字符串的可选部分捕获一个组。

例如:

在字符串 "firstName:Bill-lastName:Gates" 中,我想捕获 2 个组:

  1. 比尔
  2. 盖茨

我使用这个正则表达式:

firstName:(.*)-lastName:(.*) 

但是当 lastName 部分是可选的时,我仍然想捕获第一个 组(名字)。

我使用这个正则表达式,使姓氏部分成为可选的(在非捕获组中):

firstName:(.*)(?:-lastName:(.*))? 

使用这个更新的正则表达式,生成的组是:

  • 当 lastName 部分不存在时,例如 "firstName:Bill" 捕获的组是:

    1. 比尔
    2. /空字符串/

这是正确的,

  • 当出现 firstName 和 lastName 部分时:"firstName:Bill-lastName:Gates",组不正确:

    1. 比尔姓氏:盖茨
    2. /空/

我认为这与第一个捕获组的贪婪有关,但是当姓氏部分是可选的时,如何调整此正则表达式以使正则表达式工作?

请您参考如下方法:

你是对的,这是关于贪婪。找到第一个匹配组的分隔符。因此,如果您的名字“从不”包含破折号,则只将破折号以外的所有内容与第一个匹配组匹配。

firstName:([^-]*)(?:-lastName:(.*))? 
 
firstName:([^-]*)(?:-lastName:(.*))? 

Regular expression visualization

Debuggex Demo

如果找不到这样的分隔符,则需要采用不同的方法。即使您尝试使第一个模式“惰性”,正则表达式引擎总是更喜欢更大匹配而不是匹配额外的可选匹配。

这是因为惰性匹配组将匹配满足表达式的第一个字符串(!重要的措辞!)

可能有一个带有 look arrounds 的选项,但您也可以使用 or 语句而不提供可选匹配项:

firstName:(.*)-lastName:(.*)|firstName:(.*) 

这样,正则表达式引擎将匹配 or,但更喜欢具有 2 个匹配项的模式,因为它列在最前面。只有当那不适用时,它才会尝试单场比赛。