【问题标题】:Python Regex for a specific date format [duplicate]特定日期格式的Python正则表达式[重复]
【发布时间】:2018-09-18 07:07:47
【问题描述】:

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

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

“2018 年 3 月 30 日”、“2018 年 3 月 30 日”、“2018 年 3 月 30 日”、“2018 年 3 月 30 日”、“2018 年 3 月 30 日”、 "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”,这不应该是有效日期。

我试图在我的代码中添加“$”,但它只会让事情变得更糟,所以我想知道如何更正我的代码来解决这个问题。

附言这是一个正则表达式作业,我不允许使用 'datetime' T_T

【问题讨论】:

  • 首先,您需要使用re.X 标志重新格式化您的代码以使其可读。
  • 如果3/30/201 不是有效日期,为什么它会包含在以Examples for valid dates include 开头的字符串中?
  • @ScottHunter - 引用 OP,我创建了一个包含有效格式的字符串变量并添加了一些来检查我的代码是否可以工作。
  • @zwer:好的,但字符串的内容仍然具有误导性。
  • 3-30-201803-30-2018 之间的区别是模棱两可的 - 第一个模式必须在开头包含两位数字,以涵盖 10 月、11 月和 12 月。

标签: python regex date


【解决方案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 边界用于断言没有更多数字,否则它仍会认为“201 年 3 月 30 日”是有效日期。


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

\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 之类的内容不匹配)。

【讨论】:

  • 小心简化,在保持一致的同时允许3- 30- 2018,我将分隔符重写为([-/]|\. ?)并跳过第二个反向引用。
  • @zwer 好点,谢谢。我根据你的建议更新了。
  • 非常感谢大家的回复,真的很有帮助!!
猜你喜欢
  • 1970-01-01
  • 2014-06-23
  • 2012-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多