不理解正则表达式(1 [0-2] | 0?[1-9])用于验证时间字符串

时间:2015-10-26 02:23:13

标签: ruby regex

我找到并测试了一个正则表达式来验证时间字符串,例如11:30 AM:

^(1[0-2]|0?[1-9]):([0-5][0-9])(\s[A|P]M)\)?$

除了开头,我理解其中的大部分内容:

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

有人可以解释发生了什么吗? 1[0-2]是否有一个可以在0到2之间的第一个数字?然后我不理解|0?[1-9]

2 个答案:

答案 0 :(得分:3)

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

|将正则表达式分为两部分,其中

1[0-2]

匹配101112

0?[1-9]

19匹配,并带有可选的前导0

答案 1 :(得分:2)

我将通过在扩展模式下编写正则表达式来解释,它允许注释:

r = /
    ^     # match the beginning of the string
    (     # begin capture group 1
    1     # match 1
    [0-2] # match one of the characters 0,1,2
    |     # or
    0?    # optionally match a zero
    [1-9] # match one of the characters between 1 and 9
    )     # end capture group 1
    :     # match a colon
    (     # begin capture group 2
    [0-5] # match one of the characters between 0 and 5
    [0-9] # match one of the characters between 0 and 9
    )     # end capture group 2
    (     # begin capture group 3
    \s    # match one whitespace character
    [A|P] # match one of the characters A, | or P
    M     # match M
    )     # end capture group 3
    \)?   # optionally match a right parenthesis
    $     # match the end of the string
    /x    # extended mode

@Mischa注意到,[A|P]不正确。它应该是[AP]。这是因为"|"只是在角色类中的普通角色。

此外,我认为通过将\s移出捕获组3可以改善正则表达式。因此我们可以写一下:

r = /^(1[0-2]|0?[1-9]):([0-5][0-9])\s([AP]M)\)?$/

可以这样使用:

result = "11:39 PM" =~ r
if result
  puts "It's #{$2} minutes past #{$1}, #{ $3=='AM' ? 'anti' : 'post' } meridiem."
else
  # raise exception?
end
  #=> It's 39 minutes past 11, post meridiem.

用语言来说,修订后的正则表达式如下:

  • 匹配字符串的开头。
  • 匹配"10""11""12"或其中一个数字"1""9",可选地前面加零,并将匹配保存到捕获组1。
  • 匹配冒号。
  • 匹配"0""5"之间的数字,然后匹配"0""9"之间的数字,并保存两位数字以捕获第2组。
  • 匹配空格字符。
  • 匹配"A""P",然后是"M",并保存这两个字符以捕获第3组。
  • 可选地匹配右括号。
  • 匹配字符串的结尾。