【问题标题】:Regex: individually optional capture groups, but collectively at least one must exist正则表达式:单独可选的捕获组,但集体至少必须存在一个
【发布时间】:2014-06-30 15:53:40
【问题描述】:

我已经用多个正则表达式实现了这一点,但我很想知道是否可以用一个来实现。

我有一些代表持续时间的字符串。这些字符串的格式以“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+ 变得很尴尬,并且将返回不确定数量的捕获组。

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

编辑:

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

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)

【问题讨论】:

  • 你能用第一个,然后再检查一个空字符串吗?
  • 我可以,但我需要一个单独的正则表达式来验证格式,因为第一个将匹配任何字符串。这或多或少是我在实践中所做的,但我很好奇是否可以在同一个正则表达式中匹配和捕获有效字符串。
  • 一个单元可以完全丢失吗?例如4d5m?还是它们都在那里,但没有数字,例如 4d0h5m 或 4dxh5m?更好的是,您能否提供示例有效输入并显示应在 3 组中分别捕获的内容?
  • 我在应该回答这些问题的问题主体中添加了一些示例输入和输出。

标签: regex


【解决方案1】:

在您的正则表达式中添加一个锚定的否定前瞻来断言存在 一些 输入:

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

表达式(?!$)的意思是“这个点后面不能跟输入的结尾”,当锚定到输入的开头^(?!$)的意思是“开头后面不能跟结尾”是一样的就像说“必须有一些输入”。

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

查看此正则表达式的 live demo 与您的示例输入,包括显示正确组中单元捕获的空白输入,并且与空白输入不匹配。

【讨论】:

    【解决方案2】:

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

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

    DEMO

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多