Python Regex用于特定的日期格式

时间:2018-04-08 22:53:07

标签: python regex date

我正在研究一个python程序的正则表达式,它应该找到所有日期出现在文本中。

根据作业的描述,唯一有效的日期格式如下:

“3/30/18”,“3/30/2018”,“3-30-2018”,“03-30-2018”,“30.3.2018”, “30. 3. 2018”,“2018-03-30”

我创建了一个包含有效格式的字符串变量,并添加了一些以检查我的代码是否可行。

text_string = 'Examples for valid dates include "3/30/18", "3/30/2018", 
"3-30-2018", "03-30-2018", "30.3.2018", "30. 3. 2018", "2018-03-30", 
"3/30/1", "3/30/201", "/30/18", "3//18", "3/ /18", "3/30/", "3/301/18"'

以下是我提出的正则表达式:

match_string = re.findall('(?:\d{1,2}/\s*\d{1,2}/\s*\d{2,4})| 
(?:\d{1,2}-\s*\d{1,2}-\s*\d{2,4})|(?:\d{4}-\s*\d{1,2}-\s*\d{1,2})| 
(?:\d{1,2}.\s*\d{1,2}.\s*\d{4})', text_string)

显然,我的代码会捕获上面列出的所有7种有效日期格式,但它也返回“3/30/201”,这不应该是有效日期。

我试图在我的代码中添加'$',但它只是搞砸了更多,所以我想知道如何纠正我的代码来解决这个问题。

P.S。这是一个Regex赋值,我不允许使用'datetime'T_T

1 个答案:

答案 0 :(得分:1)

正则表达式中有问题的部分是:

\d{2,4}

这匹配2到4位数 - 这意味着3位数也被视为有效年份。如果将\d{2,4}的两个出现替换为\d{2}(?:\d{2})?)\b,则正则表达式可以正常工作:

(?:\d{1,2}/\s*\d{1,2}/\s*\d{2}(?:\d{2})?)\b|(?:\d{1,2}-\s*\d{1,2}-\s*\d{2}(?:\d{2})?)\b|(?:\d{4}-\s*\d{1,2}-\s*\d{1,2})|(?:\d{1,2}.\s*\d{1,2}.\s*\d{4})

(不要忘记使用原始字符串文字来定义正则表达式:r'(?:\d{1,2}/\s*\d{1,2}/\s*\d{2}(?:\d{2})?)\b|(?:\d{1,2}-\s*\d{1,2}-\s*\d{2}(?:\d{2})?)\b|(?:\d{4}-\s*\d{1,2}-\s*\d{1,2})|(?:\d{1,2}.\s*\d{1,2}.\s*\d{4})'

输出:

['3/30/18', '3/30/2018', '3-30-2018', '03-30-2018', '30.3.2018', '30. 3. 2018', '2018-03-30']

\d{2}(?:\d{2})?)\b正好匹配2位或4位数字 - \b边界是断言不再有数字,否则它仍会考虑" 3/30 / 201"是一个有效的日期。

最后,正则表达式可以更简洁地写成

\b\d{1,2}([-/]|\. ?)\d{1,2}\1\d{2}(?:\d{2})?\b|\b\d{4}-\d{2}-\d{2}\b

这使用捕获组断言没有混合分隔符(如3-2.2018)并且空格是一致的(因此1. 2.2018之类的东西不匹配)。