用Python中的正则表达式匹配日期?
我知道有一些与我类似的问题已经得到了回答,但读完这些问题后,我仍然没有找到我想要的解决方案 使用Python3.2.2,我需要将“月、日、年”与一个字符串中的月进行匹配,在闰年中,日是两个数字,不超过30、31或28,二月是29。(基本上是真实有效的日期) 这就是我到目前为止所做的:用Python中的正则表达式匹配日期?,python,regex,date,matching,Python,Regex,Date,Matching,我知道有一些与我类似的问题已经得到了回答,但读完这些问题后,我仍然没有找到我想要的解决方案 使用Python3.2.2,我需要将“月、日、年”与一个字符串中的月进行匹配,在闰年中,日是两个数字,不超过30、31或28,二月是29。(基本上是真实有效的日期) 这就是我到目前为止所做的: pattern = "(January|February|March|April|May|June|July|August|September|October|November|December)[,][ ](0[
pattern = "(January|February|March|April|May|June|July|August|September|October|November|December)[,][ ](0[1-9]|[12][0-9]|3[01])[,][ ]((19|20)[0-9][0-9])"
expression = re.compile(pattern)
matches = expression.findall(sampleTextFile)
我仍然不太熟悉正则表达式的语法,因此我可能会在其中包含不必要的字符(逗号和空格的[,][]感觉是错误的),但当我尝试在示例文本文件中匹配“January,26,1991”时,“matches”中的项目打印出来是('January',26',1991',19')
为什么结尾会出现额外的“19”
另外,我可以在我的正则表达式中添加或更改哪些内容来正确验证日期?我现在的计划是接受几乎所有的日期,并在以后使用高级构造将其剔除,方法是将日期分组与月份和年份分组进行比较,以确定日期是否应该是Python在
时间模块中有一个日期解析器:
import time
time.strptime("December 31, 2012", "%B %d, %Y")
如果日期格式始终相同,以上就是您所需的全部内容
因此,在实际的生产代码中,我将编写一个解析日期的正则表达式,然后使用正则表达式的结果构建一个始终采用相同格式的日期字符串
既然您在评论中说这是家庭作业,我将发布另一个答案,其中包含有关正则表达式的提示。以下是一些快速的想法:
每个建议你使用正则表达式以外的东西的人都给了你很好的建议。另一方面,现在总是学习正则表达式语法的好时机
方括号中的表达式--[…]
--匹配这些括号中的任何单个字符。因此,编写只包含一个字符的[,]
,与编写简单的未加修饰的逗号完全相同:,
.findall
方法返回字符串中所有匹配组的列表。一个组由括号--(…)
--标识,它们从左到右计数,最外层先计数。您的最终表达式如下所示:
((19|20)[0-9][0-9])
最外面的括号匹配整年,里面的括号匹配前两位数字。因此,对于像“1989”这样的日期,最后两个匹配组将是1989
和19
一个组由括号(…)
标识,它们从左到右计数,最外面的第一个。您的最终表达式如下所示:
((19|20)[0-9][0-9])
((19 | 20)[0-9][0-9])
最外面的括号匹配整年,里面的括号匹配前两位数字。因此,对于像“1989”这样的日期,两个比赛组将是1989和19。因为您不需要内部组(前两位),所以应该使用非捕获组。非捕获组以?:
开头,用法如下:(?:a | b | c)
顺便说一句,关于如何使用正则表达式,有一些很好的文档。首先,正如前面所说的,我不认为正则表达式是解决这个问题的最佳选择,而是回答您的问题。通过使用括号,您将字符串分解为几个子组,当您调用函数findall时,您将创建一个包含您创建的所有匹配组和匹配字符串的列表
((19|20)[0-9][0-9])
这是您的问题,正则表达式将匹配整个年份和19或20,这取决于年份是从19开始还是从20开始。您有以下正则表达式:
pattern = "(January|February|March|April|May|June|July|August|September|October|November|December)[,][ ](0[1-9]|[12][0-9]|3[01])[,][ ]((19|20)[0-9][0-9])"
正则表达式的一个特性是“字符类”。方括号中的字符构成字符类。因此,[,]
是与单个字符匹配的字符类,,
(逗号)。你最好用逗号
也许你想让逗号成为可选的?你可以在后面加一个问号:,?
任何放在括号内的内容都构成“匹配组”。我认为神秘的额外“19”来自一个你不想拥有的比赛小组。您可以使用以下语法创建不匹配的组:(?:
例如:
r'(?:red|blue) socks'
这将匹配“红袜子”或“蓝袜子”,但不构成匹配组。如果将其放在普通括号内:
r'((?:red|blue) socks)'
这将构成一个匹配组,其值将是“红色袜子”
或“蓝色袜子”
我认为,如果你把这些注释应用到正则表达式中,它就会工作。现在它基本上是正确的
至于根据月份验证日期,这远远超出了正则表达式的范围。您的模式将匹配“2月31日”
,并且没有简单的方法来解决这一问题。这里有一种方法可以使正则表达式匹配所需格式的任何日期(尽管您可以明显地调整逗号是否是可选的,添加月份缩写,等等):
然后我们有:
>>> r.match('January 30, 2001') is not None
True
>>> r.match('January 31, 2001') is not None
True
>>> r.match('January 32, 2001') is not None
False
>>> r.match('February 32, 2001') is not None
False
>>> r.match('February 29, 2001') is not None
False
>>> r.match('February 28, 2001') is not None
True
>>> r.match('February 29, 2000') is not None
True
>>> r.match('April 30, 1908') is not None
True
>>> r.match('April 31, 1908') is not None
False
你可能会问,这个光荣的regexp是什么
>>> print result
(?:(September|April|June|November) +(0?[1-9]|[12]\d|30), *((?:19|20)\d\d))|(?:(January|March|May|July|August|October|December) +(0?[1-9]|[12]\d|3[01]), *((?:19|20)\d\d))|(?:February +(?:(?:(0?[1-9]|1\d|2[0-8]), *((?:19|20)\d\d))|(?:(29), *((?:(?:19|20)(?:04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96))|2000))))
(我最初打算开玩笑地列举可能的日期,但基本上我最终还是手写了整个粗略的东西,除了四的倍数。)为什么需要使用正则表达式?(现在有两个问题…)我相信@Wooble所指的是“有些人在遇到问题时,会认为“我知道,我会使用正则表达式。”现在他们有两个问题。我倾向于同意。我建议提取一个字符串和两个数字(可能使用简单的正则表达式,但更可能只是通过在逗号上拆分字符串)然后用datetime测试日期是否有效。谢谢你的建议,但这是一个家庭作业,我需要做一个表达式来匹配日期