我很难理解Python正则表达式库中的group
方法。在这种情况下,我尝试根据匹配对象对字符串进行替换。
也就是说,我想用+
字典中的特定字符串替换匹配的对象(本例中为\n
和my_dict
)(rep1
和{分别为{1}}。
rep2
但在计算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
获得t
,后跟IndexError
。
任何解释和示例代码都将不胜感激。
答案 0 :(得分: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)
等访问第一个括号。
答案 1 :(得分:2)
尽管Wiktor真正的pythonic答案,仍然存在为什么OP的原始算法不起作用的问题。 基本上有两个问题:
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)