How to compose string from regex pattern with named groups and datadict in python?

Question:

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.

Asked By: Zelo

||

Answers:

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.

def repl(data, match):
    key = match.group(1)
    return data[key]

expression = r"/(?P<something>w+)/whatever/(?P<something2>w+)"
reNamedGroup = re.compile(r'(?P<(.*?)>\w+)')

data = { 'something': 'completely',
  'something2': 'different' }
print reNamedGroup.sub(lambda m: repl(data, m), expression)

This will print

/completely/whatever/different

Answered By: Hans Then

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
Answered By: unutbu
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.