我有这段代码:
for n in (range(1,10)): new = re.sub(r'(regex(group)regex)?regex', r'something'+str(n)+r'\1', old, count=1)
它将引发不匹配的组错误。但是,如果不匹配,我想在那里添加空字符串,而不是抛出错误。我怎样才能做到这一点?
注意:我的完整代码比此示例复杂得多。但是,如果您找到更好的解决方案,如何遍历比赛并在其中添加数字,则可以共享。我的完整代码:
for n in (range(1,(text.count('soutez')+1))): text = re.sub(r'(?i)(\s*\{{2}infobox medaile reprezentant(ka)?\s*\|\s*([^\}]*)\s*\}{2}\s*)?\{{2}infobox medaile soutez\s*\|\s*([^\}]*)\s*\}{2}\s*', r"\n | reprezentace"+str(n)+r" = \3\n | soutez"+str(n)+r" = \4\n | medaile"+str(n)+r" = \n", text, count=1)
在Python 3.5之前的版本中,对Pythonre.sub中失败的捕获组的反向引用未使用空字符串填充。这是在bugs.python.org上的Bug1519638描述。因此,当使用对未参与比赛的组的反向引用时,将导致错误。
re.sub
有两种方法可以解决该问题。
您可以将所有可选捕获组(如的构造(\d+)?)替换为带有空替代项(即(\d+|))的强制性捕获组。
(\d+)?
(\d+|)
这是失败的示例:
import re old = 'regexregex' new = re.sub(r'regex(group)?regex', r'something\1something', old) print(new)
更换一条线与
new = re.sub(r'regex(group|)regex', r'something\1something', old)
有用。
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(即([^}]*)) 也不会被填充 。
lambda m: m.group(n) or ''
(\s*\{{2}funcA(ka|)\s*\|\s*([^}]*)\s*\}{2}\s*|)
([^}]*)
re.sub(r'(?i)(\s*\{{2}funcA(ka|)\s*\|\s*([^\}]*)\s*\}{2}\s*|)\{{2}funcB\s*\|\s*([^\}]*)\s*\}{2}\s*', r"\n | funcA"+str(n)+r" = \3\n | funcB"+str(n)+r" = \4\n | string"+str(n)+r" = \n", text, count=1)
应该用
re.sub(r'(?i)(\s*{{funcA(ka|)\s*\|\s*([^}]*)\s*}}\s*|){{funcB\s*\|\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 re text = 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}funcB\s*\|\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'