我知道有矿类似的问题已经回答了,但通过他们看完之后我还没有我要找的解决方案。
使用Python 3.2.2,我需要匹配“月,日,年”同月为一个字符串,一天闰年是两位数字不超过30,31,或28二月和29日。 (基本上是真实有效的日期)
这是我到目前为止有:
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)
我还不太熟悉的正则表达式的语法,所以我可以在那里是不必要的字符([] []的逗号和空格感觉就像是错误的方式去了解它),但是当我尝试匹配“一月26日,1991" 年我的示例文本文件,在打印出来的物品的‘匹配’是(‘月’,‘26’,‘1991’,‘19’)。
为什么多余的“19”出现在结束了吗?
另外,我可能会增加或我正则表达式的变化,让我正确地验证日期些什么东西? 我现在的计划是接受几乎所有的日期和杂草他们出来以后使用高层次的结构由一天月份和年份分组分组比较,看看这一天应该是<31,30,29,28
任何帮助,将不胜感激,包括对我怎么样了有关设计我正则表达式建设性的批评。
Answer 1:
这里是做一个正则表达式匹配你想要的格式的任何日期(尽管你可以明显地调整了逗号是可选的,加上每月的缩写,等等)的一种方法:
years = r'((?:19|20)\d\d)'
pattern = r'(%%s) +(%%s), *%s' % years
thirties = pattern % (
"September|April|June|November",
r'0?[1-9]|[12]\d|30')
thirtyones = pattern % (
"January|March|May|July|August|October|December",
r'0?[1-9]|[12]\d|3[01]')
fours = '(?:%s)' % '|'.join('%02d' % x for x in range(4, 100, 4))
feb = r'(February) +(?:%s|%s)' % (
r'(?:(0?[1-9]|1\d|2[0-8])), *%s' % years, # 1-28 any year
r'(?:(29), *((?:(?:19|20)%s)|2000))' % fours) # 29 leap years only
result = '|'.join('(?:%s)' % x for x in (thirties, thirtyones, feb))
r = re.compile(result)
print result
然后我们有:
>>> 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
什么是这个光荣的正则表达式,你可能会问?
>>> 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))))
(我最初打算做的可能日期的舌头在脸颊枚举,但我基本上结束了手写,除了四,倍数是全毛的东西反正。)
Answer 2:
Here are some quick thoughts:
Everyone who is suggesting you use something other than regular expression is giving you very good advice. On the other hand, it's always a good time to learn more about regular expression syntax...
An expression in square brackets -- [...]
-- matches any single character inside those brackets. So writing [,]
, which only contains a single character, is exactly identical to writing a simple unadorned comma: ,
.
The .findall
method returns a list of all matching groups in the string. A group is identified by parenthese -- (...)
-- and they count from left to right, outermost first. Your final expression looks like this:
((19|20)[0-9][0-9])
The outermost parentheses match the entire year, and the inside parentheses match the first two digits. Hence, for a date like "1989", the final two match groups are going to be 1989
and 19
.
Answer 3:
一组用括号标识(...)
它们从左至右计数,最外侧的第一。 您的最终表达式如下:
((19 | 20)[0-9] [0-9])
最外层的括号中的整整一年匹配,和括号内的前两个数字相匹配。 因此,对于像“1989”的日期,这两个比赛组将是1989年和19既然你不想内组(前两位),你应该使用非捕获组来代替。 非捕获组,启动?:
像这样使用: (?:a|b|c)
顺便说一句,对于如何使用正则表达式的一些很好的文档在这里 。
Answer 4:
Python有一个日期解析器的一部分time
模块:
import time
time.strptime("December 31, 2012", "%B %d, %Y")
以上是你所需要的,如果日期格式始终是相同的。
所以,在实际生产代码,我会写一个正则表达式解析日期,然后使用结果从正则表达式来构建一个日期字符串,始终是相同的格式。
现在你说,在评论,认为这是家庭作业,我会后对正则表达式提示另一个答案。
Answer 5:
你有这样的正则表达式:
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)'
这将使比赛组,其价值将是"red socks"
或"blue socks"
我认为,如果你将这些意见,你的正则表达式,它会工作。 现在大多是正确的。
作为验证之日起对月,这是远远超出正则表达式的范围。 你的模式会匹配"February 31"
并没有简单的方法来解决这个问题。
Answer 6:
首先,其他的如说,我不认为正则表达式是最好的选择来解决这个问题,但回答你的问题。 通过使用括号你解剖串分成几个分组,当你调用函数的findAll,您将创建一个列表与您创建的所有匹配组和匹配的字符串。
((19|20)[0-9][0-9])
这是你的问题,正则表达式将根据是否在今年开始用19或20两整年和19或20相匹配。
文章来源: Matching dates with regular expressions in Python?