5

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.

1
  • 1
    Are the named groups meant to be empty? Commented Nov 7, 2012 at 11:26

2 Answers 2

5

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

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your reply. I will check that.
Take a look also under the Search and Replace section of this page: regular-expressions.info/python.html it gives a short and clear explanation about named groups.
I've just came to mark your answer as correct and also write my solution but as i see you came with much better one :). Thanks!
I added complete solution at the end of my question.
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.