基于匹配对象的字符串替换(Python)

2024-06-28 20:19:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我很难理解Python正则表达式库中的group方法。在本文中,我尝试根据匹配对象对字符串进行替换。你知道吗

也就是说,我想用my_dict字典中的特定字符串(分别用rep1rep2替换匹配的对象(+\n)。你知道吗

从这个questionanswer可以看出, 我试过这个:

content = '''
Blah - blah \n blah * blah + blah.
'''

regex = r'[+\-*/]'

for mobj in re.finditer(regex, content):
    t = mobj.lastgroup
    v = mobj.group(t)

    new_content = re.sub(regex, repl_func(mobj), content)

def repl_func(mobj):
    my_dict = { '+': 'rep1', '\n': 'rep2'}
    try:
        match = mobj.group(0)
    except AttributeError:
        match = ''
    else:
        return my_dict.get(match, '')

print(new_content)

但是在计算v时,我得到了Nonet,然后是IndexError。你知道吗

任何解释和示例代码将不胜感激。你知道吗


Tags: 对象字符串renewmymatchgroupcontent
2条回答

尽管Wiktor给出了真正的python答案,但仍然有一个问题,为什么OP的原始算法不起作用。 基本上有两个问题:

new_content = re.sub(regex, repl_func(mobj), content)的调用将用第一个匹配的替换值替换regex的所有匹配。你知道吗

正确的调用必须是new_content = re.sub(regex, repl_func, content)。 如文档所述hererepl_func通过当前匹配对象动态调用!你知道吗

repl_func(mobj)执行一些不必要的异常处理,可以简化:

my_dict = {'\n': '', '+':'rep1', '*':'rep2', '/':'rep3', '-':'rep4'}
def repl_func(mobj):
    global my_dict
    return my_dict.get(mobj.group(0), '')

这相当于Wiktor的解决方案-他只是通过使用lambda表达式摆脱了函数定义本身。你知道吗

通过这种修改,for mobj in re.finditer(regex, content):循环变得多余,因为它多次执行相同的计算。你知道吗

为了完整起见,这里有一个使用re.finditer()的工作解决方案。它从content匹配切片构建结果字符串:

my_regx = r'[\n+*/-]'
my_dict = {'\n': '', '+':'rep1'     , '*':'rep2', '/':'rep3', '-':'rep4'}
content = "A*B+C-D/E"
res = ""
cbeg = 0
for mobj in re.finditer(my_regx, content):
    # get matched string and its slice indexes
    mstr = mobj.group(0)
    mbeg = mobj.start()
    mend = mobj.end()

    # replace matched string
    mrep = my_dict.get(mstr, '')

    # append non-matched part of content plus replacement
    res += content[cbeg:mbeg] + mrep

    # set new start index of remaining slice
    cbeg = mend

# finally add remaining non-matched slice
res += content[cbeg:]
print (res)

r'[+\-*/]'正则表达式与换行符不匹配,因此您的'\n': 'rep2'将不会被使用。否则,将\n添加到regex:r'[\n+*/-]'。你知道吗

接下来,您将得到None,因为您的正则表达式不包含任何named capturing groups,请参见^{} docs

match.lastgroup
The name of the last matched capturing group, or None if the group didn’t have a name, or if no group was matched at all.

要使用匹配进行替换,甚至不需要使用re.finditer,使用re.sub和lambda作为替换:

import re
content = '''
Blah - blah \n blah * blah + blah.
'''

regex = r'[\n+*/-]'
my_dict = { '+': 'rep1', '\n': 'rep2'}
new_content = re.sub(regex, lambda m: my_dict.get(m.group(),""), content)
print(new_content)
# => rep2Blah  blah rep2 blah  blah rep1 blah.rep2

参见Python demo

m.group()获取整个匹配(整个匹配存储在match.group(0))。如果您在模式中有一对未转义的圆括号,它将创建一个capturing group,您可以使用m.group(1)等访问第一个圆括号

相关问题 更多 >