日期提取正则表达式适用于在线测试设施,但不适用于python正则表达式库

2024-09-29 03:27:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我想从句子中提取日期

这些是有效的日期类型

dd.mm.yy
dd.mm.yyyy
d.m.yy
d.m.yy
dd-mm-yy
dd-mm-yyyy
dd/mm/yy
dd/mm/yyyy

下面的正则表达式很好地完成了这项工作

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

我在多个在线正则表达式测试器上测试了它,比如https://www.regexpal.com/

然后,我在python中使用以下代码进行了尝试,但无法提取日期部分

def validate_date(text):
    date_regex = '^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$'
    return re.findall(date_regex, text)


date = validate_date("02.02.2020")
print(date)

这种行为的原因是什么


Tags: 代码texthttpscom类型datewwwvalidate
3条回答

两个问题

  1. 需要在正则表达式模式中使用原始原始原始字符串r'…'
  2. 在本例中,re.search不适用于re.findallsee answer to why does ^{} find nothing, but ^{} works?。所以可以使用搜索来查找字符串中第一个出现的日期

代码

def validate_date(text):
    date_regex = r'^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$'

    return re.search(date_regex, text)

测试

date = validate_date("02.02.2020")
print(date.group())
# Output: 02.02.2020

请在正则表达式之前附加前缀r

date_regex = r'^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$'

这里,字符串文字上的r前缀是多余的。但是,它通常用于正则表达式文本。r''(和其他带有r前缀的Python引用形式)用于定义“原始”字符串。。。也就是说,它们是(几乎)没有对字符串求值的字符串(对于\字符序列)

解决方案:

import re
def validate_date(text):
    date_regex = r'^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$'
    return re.finditer(date_regex, text)


date = validate_date("02.02.2020")
for match in date:
    print(match.group())
    # match start: match.start()
    # match end (exclusive): match.end()
    # matched text: match.group()

编写正则表达式时,请使用字符串的r'...'形式:

    date_regex = r'^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$'

这确保反斜杠(\)被解释为正则表达式的一部分(而不是在其他字符串中处理它们的方式)

相关问题 更多 >