Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PythonFindall返回意外的结果_Python_Regex_Date_Findall - Fatal编程技术网

PythonFindall返回意外的结果

PythonFindall返回意外的结果,python,regex,date,findall,Python,Regex,Date,Findall,我是Python新手,但必须制作一个正则表达式来提取dd-mm-yyy格式文本中的日期。我写了这样的东西: 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上检查了它是否有效 我返回了正确的日期,但不幸的

我是Python新手,但必须制作一个正则表达式来提取dd-mm-yyy格式文本中的日期。我写了这样的东西:

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

如何改进正则表达式以仅返回日期或删除所有非日期的内容?

我认为您需要使用非捕获组

事情是这样的:在正则表达式中,括号内的任何内容都是捕获的组,它作为匹配中捕获的项目之一出现

如果您希望使用括号对模式的一部分进行分组(例如,您可以在低于顶层的位置使用
|
),但不希望该附加组中的文本成为匹配输出中的一个单独项目,那么您希望改为使用非捕获组


要做到这一点,您可以使用
(foo)
,而不是使用
(?:foo)
-将
?:
添加到开头。这将阻止该组在最后一场比赛中捕获文本。

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.strtime
,后者知道实际日期,因此它正确地拒绝了2011年2月29日之类的内容。

re.findall
返回一个包含所有结果的元组
()
捕获。您的常规模式中有9个
()
,因此您得到了一个包含9个元素的元组。 尝试
打印格式1[0][5]
可以解决这种情况下的问题 或者改用re.search
format1=re.search('[0-2][0-9]-02-([0-2][0-9]|([0-2][0-9]| 30)-(04 | 06 | 09 | 11)-(d){4 |([0-2][0-9]| 30 | 31)-(01 | 03 12405 | 07 | 08 | 10 | 12){4},第4条)

打印格式1.组(0)

我有点困惑。你到底想要什么回报?例如,如果article='10-10-1010'并将其传递给python,您将得到>>[('','','','','','','','',10-10-1991',10',10',1'],您只是在寻找它返回'10-10-1010'吗?是吗?错?只要10-10-1010'就好了