我需要从各种字符串中获取日期月份,例如'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)?
选择匹配st
nd
rd
th
[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)
等。