Short version:
I want to crate function which replace all named groups in regular expression with coresponding data from datadict. For example:
Input: expr=r"/(?P<something>\w+)/whatever/(?P<something2>\w+)" data={"something":123, "something2": "thing"}
Output: "/123/whatever/thing"
But i have no idea how to do it.
Some addtional info:
I have code which iterate trough list of tuples containing name and pattern and trying to use re.search. In case that re.search match given string it returns name from current tuple and groupdict() (which is dict with data from re.search).
Here is the code
class UrlResolver():
def __init__(self):
self.urls = {}
def parse(self, app, url):
for pattern in self.urls[app]:
data = re.search(pattern[1], url)
if data:
return {"name": pattern[0], "data": data.groupdict()}
Now i would like to create function:
def compose(self, app, name, data):
for pattern in self.url[app]:
if pattern[0] == name:
return string composed from regex expression and data from data dict.
Above function should replace all named groups with coresponding data from datadict.
Using answer provided by Hans Then (Thanks!) and some other info here is the solution:
def _group_replacer(data, match):
data_key = match.group(1)
return data[data_key]
expression = r"\([^\(]*<([^<]*)>[^\(]*\)"
expression = re.compile(expression)
reversed = re.sub(expression, partial(_group_replacer, data), string)
function "partial" can be imported from functools
Have a look at the re.sub()
function. This function can be called with a replacement function as the second parameter. See http://docs.python.org/2/library/re.html
That function you'd have to define yourself. It would have to take a match object as its parameter. In it you should look at the match object, extract the match groups and replace them with the values from the dictionary.
You can extract the text from the string that you do not need to replace from the original string by looping through the groups and calling start, end = span(group)
on them.
EDIT
I misread your original question. I see now that you do not wish to replace the matches from the regular expressions, but the regular expressions themselves. In this case the difficult part will be to create a regular expression that matches a named regular expression. My solution still holds, but can be somewhat simpler.
To do proper penance I created the following example.
d = { 'something': 'completely',
'something2': 'different' }
def repl(m):
s = m.group(1)
return d[s]
s = "/(?P<something>\w+)/whatever/(?P<something2>\w+)"
p = re.compile(r'\(\?P<(.*?)>\\w\+\)')
print p.sub(repl, s)
This will print
/completely/whatever/different
Using a method demonstrated by F.J here, you could perform the substitution this way:
import re
data = {"something" : 123, "something2" : "thing"}
expr = r"/(?P<something>\w+)/whatever/(?P<something2>\w+)"
def matchsub(match, data):
result = list(match.string)
pat = match.re
# print(pat)
for key, index in pat.groupindex.items():
# print(key, index, data[key], match.start(index), match.end(index))
result[match.start(index):match.end(index)] = str(data[key])
return ''.join(result)
result = matchsub(re.search(expr, "hi/ABC/whatever/DEF/there"), data)
print(result)
yields
hi/123/whatever/thing/there
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With