匹配第一个出现的可选模式

时间:2019-05-25 10:41:43

标签: regex pcre

我正在尝试从混乱的字符串中提取名称,如下所示:

genus species subsp. name […] x name […] var. name; genus2 species2 subsp. name2 var. name2  
genus species subsp. name […] x name […] var. name  
genus species subsp. name […] var name  
genus species subsp. name var. name  
genus species subsp. name

[…]可以是没有规则模式的任何字符的连续。

所需的输出是:

subsp. name x name var. name  
subsp. name x name var. name  
subsp. name var. name  
subsp. name var. name  
subsp. name

我的正则表达式如下:

(?i).*?\b((?:aff|cf|ssp|subsp|var)[\.\s]+)([a-z-]+).*?(\sx\s+[a-z-]+)?.*?(\svar[\.\s]+[a-z-]+)?.*

这里是demo

我正在使用惰性量词*?在我所找到的字符串中查找某种锚点(例如subspxvar)的首次出现可以用来匹配给定的模式。 问题在于我无法在所有实例上都使用正则表达式,因为(\sx\s+[a-z-]+)?(\svar[\.\s]+[a-z-]+)?是可选的,因为匹配的模式并不在所有字符串中都存在。

是否有解决此问题的简单解决方案?

1 个答案:

答案 0 :(得分:0)

您可以将可选模式与可选的非捕获组包装在一起,以使必要的捕获组必须,并强制正则表达式引擎至少进行一次搜索模式的尝试。

这意味着您需要将所有.*?(pattern-to-extract)?模式更改为(?:.*?(pattern-to-extract))?。当整个组是可选的时,它可以匹配一个空字符串并认为作业已完成。当该组被一个可选的组包装时,它至少要尝试一次,并且保证初始的.*?会被扩展到捕获组模式所需的次数。

使用

(?i).*?\b((?:aff|cf|ssp|subsp|var)[.\s]+)([a-z-]+)(?:.*?(\sx\s+[a-z-]+))?(?:.*?(\svar[.\s]+[a-z-]+))?.*

请注意,字符类中的点与文字点匹配,无需转义。

请参见regex demo