正则表达式以匹配涉及 am/pm 的时间范围,例如上午 7 点至晚上 10 点
Regex to match time ranges involving am/pm like 7am-10pm
我写了下面的正则表达式
(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 模式以及以下内容:
它只捕获时间范围组件,比如早上 7 点到上午 10 点,应该只有 2 个匹配组,早上 7 点,上午 10 点。
它只匹配适当的时间,例如上午 111 点或下午 13 点等应该被视为不匹配。
我不知道是否可以使用正则表达式,但我们可以让正则表达式匹配正确的时间范围吗?早上 7 点到下午 1 点应该匹配,但是下午 4 点到下午 1 点应该被视为不匹配?
注:我用的是Ruby2.2.1
谢谢。
您的正则表达式中缺少 ^
(行首),这就是它在两者之间进行匹配的原因。
你必须使用:
^(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
见DEMO。
首先让我们看看你做错了什么:
13am-10pm(这不应该匹配,但是它匹配并创建 4 个匹配组 3、am、10、pm)
它只匹配适当的时间,例如上午 111 点或下午 13 点等应该被视为不匹配。
这匹配,因为您允许在此处匹配单个数字 [1-9] : (1[012]|[1-9]).
为了解决这个问题,您应该允许一个 [1-9] 数字,或者 1 + [0-2]。由于我们不知道正则表达式何时开始,我们将使用一些单词边界来确保我们有一个 "word start".
由于您不想捕获数字而是整个时间加上 am|pm 您可以使用非捕获组:
\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)
匹配以下时间格式:
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 模式以及以下内容:
它只捕获时间范围组件,比如早上 7 点到上午 10 点,应该只有 2 个匹配组,早上 7 点,上午 10 点。
它只匹配适当的时间,例如上午 111 点或下午 13 点等应该被视为不匹配。
我不知道是否可以使用正则表达式,但我们可以让正则表达式匹配正确的时间范围吗?早上 7 点到下午 1 点应该匹配,但是下午 4 点到下午 1 点应该被视为不匹配?
注:我用的是Ruby2.2.1
谢谢。
您的正则表达式中缺少 ^
(行首),这就是它在两者之间进行匹配的原因。
你必须使用:
^(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
见DEMO。
首先让我们看看你做错了什么:
13am-10pm(这不应该匹配,但是它匹配并创建 4 个匹配组 3、am、10、pm)
它只匹配适当的时间,例如上午 111 点或下午 13 点等应该被视为不匹配。
这匹配,因为您允许在此处匹配单个数字 [1-9] : (1[012]|[1-9]).
为了解决这个问题,您应该允许一个 [1-9] 数字,或者 1 + [0-2]。由于我们不知道正则表达式何时开始,我们将使用一些单词边界来确保我们有一个 "word start".
由于您不想捕获数字而是整个时间加上 am|pm 您可以使用非捕获组:
\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»