我为以下时间格式构建了一个模式匹配4:05am or 11:03pm
它在rubular上工作,但irb没有找到匹配。我该怎么修理它?
irb(main):568:0> "4:00am" =~ /[d+:d{2}(a|p)m]/
=比;0
如注释中所述,您已经将regex放在括号中,这表示字符类。很容易修复。
irb(main):001:0> "4:00am" =~ /d+:d{2}(a|p)m/
=> 0
但这也适用于:
irb(main):002:0> "4:70am" =~ /d+:d{2}(a|p)m/
=> 0
相反,您可能希望指定:
可以后跟数字0-5,然后后跟任何数字。
irb(main):005:0> "4:50am" =~ /d+:[0-5]d(a|p)m/
=> 0
irb(main):006:0> "4:70am" =~ /d+:[0-5]d(a|p)m/
=> nil
但这仍然可以检测到像"14:40am"
这样的疯狂时间。考虑到它在AM/PM拾取,我们可以假设一个12小时的时钟并进一步修改您的正则表达式:
irb(main):009:0> "14:40am" =~ /^(d|1[0-2]):[0-5]d(a|p)m$/
=> nil
irb(main):010:0> "12:40am" =~ /^(d|1[0-2]):[0-5]d(a|p)m$/
=> 0
如果您需要一个完整的正则表达式来匹配时间值,我们可以使用Regexp::Common::time Perl模块中的正则表达式。您可以通过安装模块并打印$RE{time}{hms}
来获得。
(?:(?<!d)(?:(?:(?=d)(?:[01]d|2[0123]|(?<!d)d)))[:.x20](?:(?:[0-5]d))(?:[:.x20](?:dd))?(?:s?(?:(?:(?=[AaPp])(?:[ap](?:m|.m.)?|[AP](?:M|.M.)?))))?)
小时取值范围为0 ~ 24。分值和秒值必须在0到59之间,并且必须是两位数字(即,如果小于10,它们必须有前导零)。
小时、分、秒可以用冒号、句号或空格分隔。
"seconds"值可以省略。
时间后面可以跟一个"am/pm"指标;即,下列值之一:
a am a.m. p PM p.m.上午1点。
时间与am/pm指示符之间可能有空格。
3.1.2 :018 > re = %r{(?:(?<!d)(?:(?:(?=d)(?:[01]d|2[0123]|(?<!d)d)))[:.x20](?:(?:[0-5]d))(?:[
:.x20](?:dd))?(?:s?(?:(?:(?=[AaPp])(?:[ap](?:m|.m.)?|[AP](?:M|.M.)?))))?)}
=> /(?:(?<!d)(?:(?:(?=d)(?:[01]d|2[0123]|(?<!d)d)))[:.x20](?:(?:[0-5]d))(?:[:.x20](?:...
3.1.2 :019 > re.match('12:59 a.m.')
=> #<MatchData "12:59 a.m.">
3.1.2 :020 > re.match('12:59 a.m. and stuff')
=> #<MatchData "12:59 a.m.">
3.1.2 :021 > re.match('12:59 z.m.')
=> #<MatchData "12:59">
3.1.2 :022 > re.match('13:59 a.m.')
=> #<MatchData "13:59 a.m.">
3.1.2 :023 > re.match('99:59 a.m.')
=> nil
3.1.2 :024 > re.match('11:60 a.m.')
=> nil
3.1.2 :026 > re.match('4:12')
=> #<MatchData "4:12">
3.1.2 :027 > re.match('4:1')
=> nil