我是Python的新手,但必须制作正则表达式以dd-mm-yyyy格式文本格式选择日期。我写了这样的话:
format1 = re.findall('[0-2][0-9]-02-(\d){4}|(([0-2][0-9]|30)-(04|06|09|11)-(\d){4})|(([0-2][0-9]|30|31)-(01|03|05|07|08|10|12)-(\d){4})',article)
它还会检查日期格式是否正确。我检查了它是否适用于pythex.org 我返回正确的日期,但不幸的是还有一些空的匹配和随机数字:
Match 1
1. None
2. None
3. None
4. None
5. None
6. 21-10-2005
7. 21
8. 10
9. 5
Match 2
1. None
2. None
3. None
4. None
5. None
6. 31-12-1993
7. 31
8. 12
9. 3
如何改进正则表达式以仅返回日期或删除不是日期的所有内容?
答案 0 :(得分:3)
在我看来,您需要使用非捕获组。
这就是事情:在正则表达式中,括号()
内的任何内容都是捕获的组 - 它是匹配中捕获的项目之一。< / p>
如果您想使用括号对模式的一部分进行分组(例如,以便您可以在低于顶级的某个地方使用|
),但是您不要希望该括号组内的文本成为匹配输出中的单独项目,然后您希望使用非捕获组。
要做到这一点,您将拥有(foo)
,而是使用(?:foo)
- 将?:
添加到开头。这可以防止该组在最终匹配中捕获文本。
答案 1 :(得分:1)
Amber的建议完全没问题。但我可以提一个建议吗?尽量不要将所有逻辑推入正则表达式本身。它使它几乎不可读,并且仍然没有按照书面处理角落案例(例如,它接受每年的2月29日,而不仅仅是闰年)。不要使用正则表达式来完成真正的解析器的工作。
相反,搜索一般表单,然后用专用的日期解析代码解析它,如果它通过解析,保留它。例如:
import datetime, re
def is_valid_dmy_date(datestr):
try:
datetime.datetime.strptime(datestr, '%d-%m-%Y')
except ValueError:
return False
return True
# In Python 3, wrap filter call in list() if you need a real list,
# or just iterate results of filter directly if that's all you need
all_dates = filter(is_valid_dmy_date, re.findall(r'\b\d\d-\d\d-\d{4}\b', article))
您注意到,正则表达式得到了极大的简化(我添加了\b
零宽度断言,因此它不会匹配001-01-200123
之类的内容,但如果匹配日期,您可以删除它们应该发生,即使没有字边界)。这项工作被传递给datetime.strptime
,它知道真正的日期,所以它正确地拒绝了像2011年2月29日这样的东西。
答案 2 :(得分:1)
re.findall
返回一个包含所有结果()
捕获的元组。你的常规模式中有9个()
,所以你得到一个包含9个元素的元组。
在这种情况下,尝试print format1[0][5]
可以解决问题
或者使用re.search代替
format1 = re.search('[0-2][0-9]-02-(\d){4}|(([0-2][0-9]|30)-(04|06|09|11)-(\d){4})|(([0-2][0-9]|30|31)-(01|03|05|07|08|10|12)-(\d){4})',article)
print format1.group(0)