根本原因
在Python
3.5之前的版本中,对Python
re.sub中失败的捕获组的反向引用未使用空字符串填充。这是在bugs.python.org上的Bug1519638描述。因此,当使用对未参与比赛的组的反向引用时,将导致错误。
有两种方法可以解决该问题。
解决方案1:添加空替代项以使可选组成为必需项
您可以将所有可选捕获组(如的构造
(d+)?)替换为带有空替代项(即
(d+|))的强制性捕获组。
这是失败的示例:
import reold = 'regexregex'new = re.sub(r'regex(group)?regex', r'something1something', old)print(new)
更换一条线与
new = re.sub(r'regex(group|)regex', r'something1something', old)
有用。
解决方案2:在替换中使用lambda表达式并检查该组是否不是 None
如果您在另一个可选组中有可选组,则此方法是必需的。
您可以使用lambda在更换零件来检查组被初始化,不
None与
lambda m: m.group(n) or ''。 在您的情况下 ,
请使用此解决方案
,因为替换模式中有两个后向引用-#3和#4-但是某些匹配项(请参见Match
1和3)没有初始化捕获组3。发生这种情况是因为整个第一部分-
(s*{{2}funcA(ka|)s*|s*([^}]*)s*}{2}s*|)不参与比赛,并且即使添加了一个空的替代项 ,内部的Capture组3(即
([^}]*)) 也不会被填充 。
re.sub(r'(?i)(s*{{2}funcA(ka|)s*|s*([^}]*)s*}{2}s*|){{2}funcBs*|s*([^}]*)s*}{2}s*', r"n | funcA"+str(n)+r" = 3n | funcB"+str(n)+r" = 4n | string"+str(n)+r" = n", text, count=1)应该用
re.sub(r'(?i)(s*{{funcA(ka|)s*|s*([^}]*)s*}}s*|){{funcBs*|s*([^}]*)s*}}s*', lambda m: r"n | funcA"+str(n)+r" = " + (m.group(3) or '') + "n | funcB" + str(n) + r" = " + (m.group(4) or '') + "n | string" + str(n) + r" = n", text, count=1)见IDEONE演示
import retext = r'''{{funcB|param1}}*some string*{{funcA|param2}}{{funcB|param3}}*some string2*{{funcB|param4}}*some string3*{{funcAka|param5}}{{funcB|param6}}*some string4*'''for n in (range(1,(text.count('funcB')+1))): text = re.sub(r'(?i)(s*{{2}funcA(ka|)s*|s*([^}]*)s*}{2}s*|){{2}funcBs*|s*([^}]*)s*}{2}s*', lambda m: r"n | funcA"+str(n)+r" = "+(m.group(3) or '')+"n | funcB"+str(n)+r" = "+(m.group(4) or '')+"n | string"+str(n)+r" = n", text, count=1)assert text == r'''| funcA1 =| funcB1 = param1| string1 =*some string*| funcA2 = param2| funcB2 = param3| string2 =*some string2*| funcA3 =| funcB3 = param4| string3 =*some string3*| funcA4 = param5| funcB4 = param6| string4 =*some string4*'''print 'ok'


