Python Regex re.search - groupdict() -日期格式匹配



我需要从各种字符串中获取日期月份,例如'14oct', '14oct', '14.10', '14 10'和'14/10'。对于这些情况,我下面的代码工作良好。

query = '14.oct'
print(re.search(r'(?P<date>bd{1,2})(?:b|st|nd|rd|th)?(?:[s.-/_\,]*)(?P<month>d{1,2}|[a-z]{3,9})', query, re.I).groupdict())

结果: -

{'date': '14', 'month': 'oct'}

但是对于这个例子(1410),它仍然捕获日期和月份。但我不希望这样,因为这将是整个字符串的另一种数字格式,而不会被视为日期和月份。结果应该是None

如何改变这个的搜索模式?(仅含groupdict())


编辑:-

上述数字(1410)中的旁合只是为了区别于其他文本。我想说的是1410

下面的解决方案是我想要的,我通过在regex模式中添加(?!d{3,}b)从@the-fourth-bird的答案中得到了这个想法。

谢谢🙏🏽

最终解决

import re
queries = ['14 10', '14.10', '1410', '14-10', '14/10', '14,10', '17800', '14th oct', '14thoct', '14th-oct', '14th/oct', '14-oct', '14.oct', '14oct']
max_indent = len(max(queries, key = len)) + 1
for query in queries:
if resp := re.search(r'(?P<date>b(?!d{3,}b)d{1,2})(?:b|st|[nr]d|th)?(?:[s.-/_\,-]*)(?P<month>d{1,2}|[a-z]{3,9})', query, re.I):
print(f"{query:{max_indent}}- {resp.groupdict()}")
else:
print(f"{query:{max_indent}}- 'Not a date'")

结果: -

14 10    - {'date': '14', 'month': '10'}
14.10    - {'date': '14', 'month': '10'}
1410     - 'Not a date'
14-10    - {'date': '14', 'month': '10'}
14/10    - {'date': '14', 'month': '10'}
14,10    - {'date': '14', 'month': '10'}
17800    - 'Not a date'
14th oct - {'date': '14', 'month': 'oct'}
14thoct  - {'date': '14', 'month': 'oct'}
14th-oct - {'date': '14', 'month': 'oct'}
14th/oct - {'date': '14', 'month': 'oct'}
14-oct   - {'date': '14', 'month': 'oct'}
14.oct   - {'date': '14', 'month': 'oct'}
14oct    - {'date': '14', 'month': 'oct'}

不确定是否您不想匹配1410仅为4位数字或(1410)与括号,但要排除匹配,您可以确保没有连续的4位数字:

(?P<date>b(?!d{4}b)d{1,2})(?:st|[nr]d|th)?[s./_\,-]*(?P<month>d{1,2}|[a-z]{3,9})

Regex演示

不匹配括号

之间的任何日期
([^()]*)|(?P<date>bd{1,2})(?:st|[nr]d|th)?[s./_\,-]*(?P<month>d{1,2}|[a-z]{3,9})
  • ([^()]*)从左到右括号匹配
  • |
  • (?P<date>bd{1,2})匹配1-2位数字
  • (?:st|[nr]d|th)?选择匹配stndrdth
  • [s./_\,-]*可选地重复匹配列出的任何
  • (?P<month>d{1,2}|[a-z]{3,9})匹配1-2位数字或3-9个字符a-z

Regex演示例如

import re
pattern = r"([^()]*)|(?P<date>bd{1,2})(?:st|[nr]d|th)?(?:[s./_\,-]*)(?P<month>d{1,2}|[a-z]{3,9})"
strings = ["14th oct", "14oct", "14.10", "14 10", "14/10", "1410", "(1410)"]
for s in strings:
m = re.search(pattern, s, re.I)
if m.group(1):
print(m.groupdict())
else:
print(f"{s} --> Not valid")

输出
{'date': '14', 'month': 'oct'}
{'date': '14', 'month': 'oct'}
{'date': '14', 'month': '10'}
{'date': '14', 'month': '10'}
{'date': '14', 'month': '10'}
{'date': '14', 'month': '10'}
(1410) --> Not valid

如何更改此搜索模式?

您可以尝试使用反向回溯断言文字(和反向回溯断言文字),如下所示

import re
query = '14.oct'
noquery = '(1410)'
print(re.search(r'(?<!()(?P<date>bd{1,2})(?:b|st|nd|rd|th)?(?:[s.-/_\,]*)(?P<month>d{1,2}|[a-z]{3,9})(?!))', query, re.I).groupdict())
print(re.search(r'(?<!()(?P<date>bd{1,2})(?:b|st|nd|rd|th)?(?:[s.-/_\,]*)(?P<month>d{1,2}|[a-z]{3,9})(?!))', noquery, re.I))

输出
{'date': '14', 'month': 'oct'}
None

注意,它不阻止所有带括号的形式,即不仅(1410),而且(14 10),(14/10)等。

相关内容

  • 没有找到相关文章

最新更新