正则表达式:匹配格式错误的日期

时间:2015-09-21 10:10:32

标签: regex python-3.x

我正试图从以下OCR字符串中获取日期(没有时间):

04.10.2015, in USD
04.10.20 15, in EUR
04,1 0.2015, in XYZ
1 1. 10.2 01 5, in XYZ
0 1.11.201 5 12:30
1 1,0 3, 2 0 1 5 1 2:3 0

使用以下表达式我可以捕捉日期,但我不能跳过“12”小时:

([\d\s]{2,}(?:\.|,)[\d\s]{2,}(?:\.|,)[\d\s]{4,})

我怎样才能让它发挥作用?用简单的英文,如果在数字和空格/标签的混合中找到4位数,我怎么能让最后一部分停止?

3 个答案:

答案 0 :(得分:3)

通过捕捉一行中的前8位数字,您将获得日期。

  • \D是任何非数字字符
  • \d是一个数字字符
  • (?:...)是一个将被忽略的群组
  • ^\D*用于忽略行的开头,直到我们得到一个数字

我们匹配8位数字后跟任何非数字字符,从找到的第一个数字开始。

import re
p = re.compile(ur'^\D*((?:\d\D*?){8})', re.MULTILINE)
test_str = u"""04.10.2015, in USD
    04.10.20 15, in EUR
    04,1 0.2015, in XYZ
    1 1. 10.2 01 5, in XYZ
    0 1.11.201 5 12:30
    1 1,0 3, 2 0 1 5 1 2:3 0
"""

print re.findall(p, test_str)

在此进行测试:https://regex101.com/r/eQ8zJ9/4

然后,您可以过滤掉任何非数字以获取日期:

from datetime import datetime

for s in re.findall(p, test_str):
    digits = re.sub(ur'\D', '', s)
    print datetime.strptime(digits, '%d%m%Y')

答案 1 :(得分:1)

您也可以尝试:

((?:\d\s*){2})[,.-]((?:\s*\d\s*){2})[,.-]((?:\s*\d){4})

DEMO

不受行首的限制。它匹配的还有一个选择的分隔符beetwen数字,如,.-。因为在这种格式化的文本中可能会有更多8位数的混沌数字序列。

答案 2 :(得分:1)

另一个答案很好而且简短,但如果分隔符很重要:

((?:(?:\d\s*){2}[.,]\s*){2}(?:\d\s*?){4})

关键是:

(?:\d\s*?){}

使用可选但非贪婪的空格捕获数字。

我还冒昧地将(?:\.|,)缩短为[.,]