2016-11-24 87 views
1

我很难理解Python正则表达式库中的group方法。在这种情况下,我尝试根据匹配对象对字符串进行替换。基于匹配对象的字符串替换(Python)

即,我想(分别与rep1rep2)取代匹配的对象(在此实例中+\n)与所述my_dict字典一个特定的字符串。

由该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) 

,但我得到了None随后tIndexError计算v时。

任何解释和示例代码将不胜感激。

+0

很难猜测你的代码是应该做的(有许多语法错误,压痕坏了,逻辑不清)。更好地提供一个例子来描述你想达到的目标。 – TomR8

+0

@ TomR8道歉!我修复了所有语法问题和拼写错误(希望)。 –

回答

2

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

接下来,你会得到None,因为你的正则表达式不包含任何named capturing groups,看到re docs

match.lastgroup
最后匹配的捕获组的名称,或None如果组没有有一个名字,或者如果没有任何组匹配

要更换使用匹配,你甚至不需要使用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)

2

尽管Wiktor的的真正Python的答案,还是有问题,为什么OP的原单算法止跌没有工作。 基本上有2个问题:

new_content = re.sub(regex, repl_func(mobj), content)通话将取代所有的最先匹配重置价值相匹配的regex

正确的电话必须是new_content = re.sub(regex, repl_func, content)。 如文档here所示,repl_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)