【问题标题】:regex with optional capture group带有可选捕获组的正则表达式
【发布时间】:2018-08-15 16:35:09
【问题描述】:

我正在尝试使用正则表达式从字符串中获取数量、单位和内容。单位和物质来自预定义的列表。

所以:

  • “2公斤水”应该返回:2, kg, water
  • “1 加仑原油”应返回:1, gallon, oil

我可以使用以下正则表达式来实现这一点: (\d*) ?(kg|ml|gallon).*(water|oil)

问题是我不知道如何使最后一个捕获组成为可选。如果物质不在预定义列表中,我仍然想获取数量和单位。所以:

  • “1 加仑柴油”应返回:1, gallon 或 1, gallon, ''

我已尝试将最后一个组包装在一个可选的非捕获组中,如下所述:Regex with optional capture fields 但没有成功。

这里是在线正则表达式测试器中的当前正则:https://regex101.com/r/hV3wQ3/55

【问题讨论】:

  • 为什么不直接捕获(\d+) ?(kg|ml|gallon) of (.*) 并稍后查看预定义物质列表?
  • 使用? 量词它匹配0 到1 次。 (water|oil)?
  • @S.Jovan 那行不通。它总是无法捕获任何东西。

标签: regex capture-group


【解决方案1】:

您正在尝试使用(\d+) ?(kg|ml|gallon).*(?:(water|oil))?,并且此模式无法捕获water / oil。问题是 .* 抓取除换行符之外的任何 0+ 字符直到字符串/行的末尾,当正则表达式索引存在时,(?:(water|oil))? 在字符串末尾尝试。由于(?:(water|oil))?可以匹配空字符串,所以匹配到字符串末尾的位置,并返回匹配。

您仍然可以强制使用捕获组,但将.* 和捕获组与可选的非捕获组包装起来:

(\d+) ?(kg|ml|gallon)(?:.*(water|oil))?
                     ^^^             ^^ 

见regex demo

(?:.*(water|oil))? 匹配除换行符 (.*) 和 water 或 oil 之外的任何 0+ 字符的 1 次或 0 次(贪婪地)匹配。

【讨论】:

  • 很好,这就像一个魅力。我明白这是如何工作的。但我不明白为什么(\d+) ?(kg|ml|gallon).*(?:(water|oil))? 不起作用。为什么这与第 3 组中的(水|油)不匹配?
  • @JasperZelf 因为.* 已经抢占了water 或oil,所以无需回溯,因为(...)? 匹配任何内容,甚至是空字符串(位置)。
  • 那是完美的感觉。谢谢解释
猜你喜欢
  • 1970-01-01
  • 2022-11-21
  • 2011-07-26
  • 2015-08-20
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多