最简单的方法是使用命名组,即代替普通(.*)
使用(?P<name>.*)
,然后使用对象的groupdict()
方法Match
。
但是,如果您无法更改问题的输入(因为您是从另一个库或任何其他原因获取它们,您可以通过key_mask
usingre.sub
和 using 一个简单的函数自动创建命名组正则表达式repl
:
import re
def to_named_group(match):
return '(?P<{}>.*)'.format(re.escape(match.group(0)[1:-1]))
def make_regex(key_mask):
return re.compile(re.sub(r'\{[^}]+\}', to_named_group, key_mask))
def find_matches(key_mask, text):
return make_regex(key_mask).match(text).groupdict()
用作:
In [10]: find_matches('foo/{one}/bar/{two}/hello/{world}', 'foo/test/bar/something/hello/xxx')
Out[10]: {'one': 'test', 'two': 'something', 'world': 'xxx'}
根据您的评论更新:
很容易传递to_named_group
有关要生成的正则表达式的更多信息。例如,您可以将代码更改为:
import re
from functools import partial
def to_named_groups(match, regexes):
group_name = re.escape(match.group(0)[1:-1])
group_regex = regexes.get(group_name, '.*')
return '(?P<{}>{})'.format(group_name, group_regex)
def make_regex(key_mask, regexes):
regex = re.sub(r'\{[^}]+\}', partial(to_named_groups, regexes=regexes),
key_mask)
return re.compile(regex)
def find_matches(key_mask, text, regexes=None):
if regexes is None:
regexes = {}
try:
return make_regex(key_mask, regexes).search(text).groupdict()
except AttributeError:
return None
通过这种方式,您可以控制每个命名组应匹配的内容。