Regex可匹配上午/下午的时间范围,如上午7点至晚上10点



我已经编写了以下regex

(1[012]|[1-9])(am|pm)-(1[012]|[1-9])(am|pm)

以匹配以下类型的时间格式:

7am-10pm (matches correctly and creates 4 match groups 7, am, 10, pm)
13am-10pm (this should not be matched, however it matches and creates 4 match groups 3, am, 10, pm)
10pm (this doesn't match as expected because it doesn't specify the time range end)
111am-10pm (this should not be matched, however it matches and creates 4 match groups 11, am, 10, pm)

我如何改进我的正则表达式,使我不需要重复数字和am/pm模式以及以下内容:

  1. 它只捕获时间范围分量,比如在早上7点到10点,应该只有2个匹配组,早上7点和10点。

  2. 它只匹配适当的时间,例如上午11点或下午13点等应被视为不匹配。

  3. 我不知道是否可以使用正则表达式,但我们能让正则表达式与正确的时间范围匹配吗?例如,早上7点到下午1点应该匹配,但下午4点到1点应该被视为不匹配?

注意:我使用的是Ruby 2.2.1

谢谢。

首先让我们看看你做错了什么:

13mm-10pm(这不应该匹配,但它匹配并创建了4个匹配组3,am,10,pm)

它只匹配适当的时间,例如上午11点或下午13点等应被视为不匹配

这是匹配的,因为您允许在此处匹配一个位数[1-9]:(1[012]|[1-9])。

为了解决这个问题,您应该允许一个[1-9]数字,或者1+[0-2]。由于我们不知道正则表达式何时开始,我们将使用一些单词边界来确保我们有一个"单词开始"。

由于您不想捕获数字,而是整个时间加上上午|下午,因此可以使用非捕获组:

b((?:1[0-2]|[1-9])

然后,这只是一个重复我们自己并添加破折号的问题:

b((?:1[0-2]|[1-9])[ap]m)-((?:1[0-2]|[1-9])[ap]m)

关于第3点。嗯,是的,可以用正则表达式来实现这一点,但最好在获得组1和组2后添加一个逻辑检查,看看时间范围是否真的有意义。

所有这些都是你得到的:

# b((?:1[0-2]|[1-9])[ap]m)-((?:1[0-2]|[1-9])[ap]m)
# 
# 
# Assert position at a word boundary «b»
# Match the regular expression below and capture its match into backreference number 1 «((?:1[0-2]|[1-9])[ap]m)»
#    Match the regular expression below «(?:1[0-2]|[1-9])»
#       Match either the regular expression below (attempting the next alternative only if this one fails) «1[0-2]»
#          Match the character “1” literally «1»
#          Match a single character in the range between “0” and “2” «[0-2]»
#       Or match regular expression number 2 below (the entire group fails if this one fails to match) «[1-9]»
#          Match a single character in the range between “1” and “9” «[1-9]»
#    Match a single character present in the list “ap” «[ap]»
#    Match the character “m” literally «m»
# Match the character “-” literally «-»
# Match the regular expression below and capture its match into backreference number 2 «((?:1[0-2]|[1-9])[ap]m)»
#    Match the regular expression below «(?:1[0-2]|[1-9])»
#       Match either the regular expression below (attempting the next alternative only if this one fails) «1[0-2]»
#          Match the character “1” literally «1»
#          Match a single character in the range between “0” and “2” «[0-2]»
#       Or match regular expression number 2 below (the entire group fails if this one fails to match) «[1-9]»
#          Match a single character in the range between “1” and “9” «[1-9]»
#    Match a single character present in the list “ap” «[ap]»
#    Match the character “m” literally «m»

正则表达式中缺少^(行首),这就是为什么它在两者之间匹配的原因。

你必须使用:

^(1[012]|[1-9])(am|pm)-(1[012]|[1-9])(am|pm)

更好的解决方案:如果您的模式不总是从新行开始,您也可以使用b(边界)。

b(1[012]|[1-9])(am|pm)-(1[012]|[1-9])(am|pm)b

请参见演示。

相关内容

最新更新