1

我在下面的正则表达式匹配中做错了什么

>>> import re
>>> d="30-12-2001"
>>> re.findall(r"\b[1-31][/-:][1-12][/-:][1981-2011]\b",d)
[]
4

6 回答 6

6

[1-31]匹配1-31基本上是 1、2 或 3。除非它是 0-9 的子集,否则不能匹配数字范围。同样适用于[1981-2011]恰好匹配 0、1、2、8 或 9 的一个字符。

最好的解决方案是简单地匹配任何数字,然后稍后使用 python 本身检查数字。这样的日期31-02-2012没有任何意义 - 并且很难进行正则表达式检查。让它也能正确处理闰年会使它变得更加困难或不可能。这是一个匹配任何看起来像dd-mm-yyyy日期的正则表达式:\b\d{1,2}[-/:]\d{1,2}[-/:]\d{4}\b

但是,我强烈建议不要允许任何-,:和通常用于时间的,/通常用于美国编写日期的方式 ( ) 和ISO 方式 ( )。根本不处理EU语法。:/mm/dd/yyyy-yyyy-mm-dddd.mm.yyyy

如果字符串只包含日期,则根本不需要正则表达式 - 请strptime()改用。

总而言之,告诉用户您期望的日期格式并解析该格式,拒绝其他任何内容。否则你会得到模棱两可的情况,例如04/05/2012(是 4 月 5 日还是 5 月 4 日?)。

于 2012-04-10T10:26:50.340 回答
1

[1-31]并不意味着你认为它意味着什么。方括号语法匹配一个字符范围,而不是一个数字范围。用正则表达式匹配一系列数字是可能的,但很笨拙。

如果你真的想为此使用正则表达式(而不是日期解析库),你最好匹配正确位数的所有数字,捕获值,然后自己检查值:

>>> import re
>>> d="30-12-2001"
>>> >>> re.findall(r"\b([0-9]{1,2})[-/:]([0-9]{1,2})[-/:]([0-9]{4})\b",d)
[('30', '12', '2001')]

无论如何,您都必须进行实际日期验证,以捕获无效日期,例如31-02-2012.

(请注意,这[/-:]也不起作用,因为它被解释为一个范围。[-/:]改用 -​​ 将连字符放在前面可以防止它被解释为范围分隔符。)

于 2012-04-10T10:31:09.870 回答
1

正则表达式不理解数字;对正则表达式来说,1只是字符串的一个字符——就是这样的东西a。因此,例如,[1-31]被解析为包含范围1-3和(冗余)单个符号的字符类1

您不想使用正则表达式来解析日期。已经有一个用于处理日期解析的内置模块:

>>> import datetime
>>> datetime.datetime.strptime('30-12-2001', '%d-%m-%Y')
datetime.datetime(2001, 12, 30, 0, 0) # an object representing the date.

这也会为您执行所有辅助检查(例如尝试参考 2 月 31 日)。如果您想处理多种类型的分隔符,您可以简单地.replace将它们放在原始字符串中,以便它们都变成相同的分隔符,然后在您的格式中使用它。

于 2012-04-10T10:33:00.880 回答
1

你可能做错了。这里的其他一些回复正在帮助您使用正则表达式,但我建议您使用该datetime.strptime方法将格式化日期转换为日期时间对象,并对该对象进行进一步的逻辑处理:

>>> import datetime
>>> datetime.strptime('30-12-2001', '%d-%m-%Y')
datetime.datetime(2001, 12, 30, 0, 0)

有关 strptime 方法及其格式字符串的更多信息。

于 2012-04-10T10:35:01.713 回答
1

正则表达式 = r'(0?[1-9]|[12][0-9]|3[01])/(0?[1-9]|1[012])/((19|20)\ d\d)'

(#组#1的开始
 0?[1-9] # 01-09 或 1-9
 | # ..或者
 [12][0-9] # 10-19 或 20-29
 | # ..或者
 3 [01] # 30, 31
) #1 组结束
  /# 后跟一个“/”
   ( # 组 #2 开始
    0?[1-9] # 01-09 或 1-9
    | # ..或者
    1[012]#10,11,12
    ) # 组 #2 结束
     /# 后跟一个“/”
      (#组开始#3
       (19|20)\\d\\d # 19[0-9][0-9] 或 20[0-9][0-9]
       ) # 组结束 #3
于 2012-06-30T19:41:37.420 回答
0

也许你可以试试这个正则表达式

^((0|1|2)[0-9]{1}|(3)[0-1]{1})/((0)[0-9]{1}|(1)[0-2]{1})/((19)[0-9]{2}|(20)[0-9]{2})$

本场比赛为(01 至 31)/(01 至 12)/(1900 至 2099)

于 2018-02-09T13:27:13.100 回答