我在下面的正则表达式匹配中做错了什么
>>> import re
>>> d="30-12-2001"
>>> re.findall(r"\b[1-31][/-:][1-12][/-:][1981-2011]\b",d)
[]
[1-31]
匹配1-3
,1
基本上是 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-dd
dd.mm.yyyy
如果字符串只包含日期,则根本不需要正则表达式 - 请strptime()
改用。
总而言之,告诉用户您期望的日期格式并解析该格式,拒绝其他任何内容。否则你会得到模棱两可的情况,例如04/05/2012
(是 4 月 5 日还是 5 月 4 日?)。
[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
.
(请注意,这[/-:]
也不起作用,因为它被解释为一个范围。[-/:]
改用 - 将连字符放在前面可以防止它被解释为范围分隔符。)
正则表达式不理解数字;对正则表达式来说,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
将它们放在原始字符串中,以便它们都变成相同的分隔符,然后在您的格式中使用它。
你可能做错了。这里的其他一些回复正在帮助您使用正则表达式,但我建议您使用该datetime.strptime
方法将格式化日期转换为日期时间对象,并对该对象进行进一步的逻辑处理:
>>> import datetime
>>> datetime.strptime('30-12-2001', '%d-%m-%Y')
datetime.datetime(2001, 12, 30, 0, 0)
正则表达式 = 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
也许你可以试试这个正则表达式
^((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)