正则表达式:单独可选的捕获组,但总共至少必须存在一个

时间:2014-06-30 15:53:40

标签: regex

我已经使用多个正则表达式实现了这一点,但我有兴趣知道是否可以使用一个正则表达式。

我有一些表示持续时间的字符串。这些字符串的格式为" 4d10h30m",表示持续时间为4天,10小时和30分钟。持续时间(天,小时或分钟)中的每个单位是可选的,因此" 4d"是一个有效的字符串," 10h30m"。

我想要的是一个正则表达式(javascript,如果它很重要)可靠地返回三个捕获组,每个捕获组包含一个单元的值。所以在" 4d10h30m"例如,将正则表达式与此字符串匹配应返回[" 4"," 10"," 30"]。如果缺少该单元,它在元组中的位置可以包含几乎不是非零整数的任何东西(0," 0",null或空字符串都很好)。

我考虑过的两种方法如下:

/(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?/

匹配空字符串;和一些变化:

/((?:\d+[dhm]){1,3})/

这使得仅仅捕获\ d +并且将返回不确定数量的捕获组变得尴尬。

我怀疑后者不是首发。如果有一个指定&#34的正则表达式构造,前者将起作用;这些组中的任何一个都是单独可选的,但总的来说,它们中至少有一个必须存在&#34 ;?在细胞自动机的限制下,这似乎是可行的,但我不知道它是如何在正则表达式中实现的,或者即使它可以实现。

编辑:

根据请求,一些示例输入及其输出:

2d1h5m # ["2","1","5"]
3h20m  # ["", "3", "20"]
4d10m  # ["4", "", "10"]
2d     # ["2", "", ""]
6h     # ["", "6", ""]
1x20y  # no match (invalid units)
2dh20m # no match (no units allowed without a value)
21020  # no match (no units)
1h2d5m # no match (disordered units)
xd5m   # no match (non-numeral value)

2 个答案:

答案 0 :(得分:4)

为你的正则表达式添加一个锚定的负面预测来断言某些输入:

^(?!$)(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?$

表达式(?!$)表示“此点不能跟随输入结束”,并且当锚定到输入^(?!$)的开头时意味着“开头不能跟着结束”这与说“必须有一些输入”是一样的。

使用锚定前瞻是一种方便的方法来断言正则表达式的输入的总长度,否则将声明输入的格式。

使用您的示例输入查看此正则表达式的live demo,包括空白输入,显示正确组中单位的捕获,以及不匹配空白输入。

答案 1 :(得分:0)

以下正则表达式会捕获输入字符串中是否存在dhm的数字,

(\d)d?(\d{2})h?(\d{2})m?

DEMO