regex - 匹配可选模式的第一次出现
问题描述
我正在尝试在混乱的字符串中提取名称,如下所示:
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
Where[…]
可以是没有规则模式的任何字符的连续。
所需的输出是:
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-]+)?.*
这是一个演示。
我正在使用惰性量词*?
来查找字符串中某种锚点(例如subsp
,x
和var
)的第一次出现,我可以使用这些锚点来匹配给定的模式。问题是我无法让正则表达式适用于所有实例,因为(\sx\s+[a-z-]+)?
并且(\svar[\.\s]+[a-z-]+)?
是可选的,因为匹配的模式并不存在于所有字符串中。
是否有解决此问题的简单解决方案?
解决方案
您可以使用可选的非捕获组包装可选模式,以使必要的捕获组成为强制性的,并强制正则表达式引擎至少尝试一次搜索模式。
这意味着您需要将所有.*?(pattern-to-extract)?
模式更改为(?:.*?(pattern-to-extract))?
. 当整个组是可选的时,它可能会匹配一个空字符串并认为工作已完成。当该组被一个可选组包裹时,它至少会尝试一次,并且.*?
保证初始值会根据需要扩展多次以达到捕获组模式。
利用
(?i).*?\b((?:aff|cf|ssp|subsp|var)[.\s]+)([a-z-]+)(?:.*?(\sx\s+[a-z-]+))?(?:.*?(\svar[.\s]+[a-z-]+))?.*
请注意,字符类中的点与文字点匹配,无需转义它们。
请参阅正则表达式演示。
推荐阅读
- javascript - 从 MongoDB 检索的 Javascript 对象中删除一个值
- amazon-web-services - AWS 上的 saltstack 最佳实践
- mobile-safari - 在 Safari 中全屏
- reactjs - 两个从属日期选择器,其中开始日期永远不能大于结束日期
- javascript - 如何检测应用程序中按下的键盘组合?
- amazon-web-services - CloudFormation 中更新和导入的区别
- python - Geopandas:保存为csv时如何指定数据类型?
- json - 没有键的结构/映射数组
- json - 如何在 API 调用完成后和组件呈现之前更新状态
- php - 检查数据库中是否有另一个用户名不起作用