简体   繁体   English

如何在python中使用命名组和datadict从正则表达式模式组成字符串?

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

Short version: 精简版:

I want to crate function which replace all named groups in regular expression with coresponding data from datadict. 我想创建一个函数,它用正则表达式中的所有命名组替换来自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. 我有代码,它迭代包含名称和模式的元组列表,并尝试使用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). 如果re.search匹配给定字符串,则返回当前元组和groupdict()的名称(这是来自re.search的数据的dict)。

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. 上面的函数应该用来自datadict的相应数据替换所有命名组。

SOLUTION

Using answer provided by Hans Then (Thanks!) and some other info here is the solution: 使用Hans Then提供的答案(谢谢!)以及其他一些信息是解决方案:

    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 函数“partial”可以从functools导入

Have a look at the re.sub() function. 看看re.sub()函数。 This function can be called with a replacement function as the second parameter. 可以使用替换函数作为第二个参数调用此函数。 See http://docs.python.org/2/library/re.html 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. 您可以提取,你不需要通过组循环,并呼吁从原来的字符串替换字符串文本start, end = span(group)在他们身上。

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 FJ here , you could perform the substitution this way: 使用FJ在此处演示的方法,您可以通过以下方式执行替换:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM