Python反向引用替换不按预期工作

3

我的模式中有两个命名组:myFlagid,我想在id组之前立即添加另一个myFlag

这是我的当前代码:

# i'm using Python 3.4.2
import re
import os
contents = b'''
xdlg::xdlg(x_app* pApp, CWnd* pParent)
    : customized_dlg((UINT)0, pParent, pApp)
    , m_pReaderApp(pApp)
    , m_info(pApp)
{

}
'''

pattern = rb'(?P<myFlag>[a-zA-Z0-9_]+)::(?P=myFlag).+:.+(?P<id>\(UINT\)0 *,)'
res = re.search(pattern, contents, re.DOTALL)
if None != res:
    print(res.groups()) # the output is (b'xdlg', b'(UINT)0,')

# 'replPattern' becomes b'(?P<myFlag>[a-zA-Z0-9_]+)::(?P=myFlag).+:.+((?P=myFlag)\\(UINT\\)0 *,)'
replPattern = pattern.replace(b'?P<id>', b'(?P=myFlag)', re.DOTALL)
print(replPattern)
contents = re.sub(pattern, replPattern, contents)
print(contents)

预期结果应该是:
xdlg::xdlg(x_app* pApp, CWnd* pParent)
    : customized_dlg(xdlg(UINT)0, pParent, pApp)
    , m_pReaderApp(pApp)
    , m_info(pApp)
{

}

但现在的结果与原来的相同:
 xdlg::xdlg(x_app* pApp, CWnd* pParent)
    : customized_dlg((UINT)0, pParent, pApp)
    , m_pReaderApp(pApp)
    , m_info(pApp)
{

}

此外,输入中没有第三个“xdlg”字符串。你在这里究竟想要实现什么? - Martijn Pieters
因为我想用'myFlag'组替换字符串,所以必须用括号将它们括起来(Python语法)。 - O'Skywalker
这里的预期输出是什么?你试图解决什么问题? - Martijn Pieters
你用反向引用替换了命名组的名称,这里的正则表达式语法毫无意义。 - Martijn Pieters
@o11c,感谢您的建议。但是使用're.DOTALL'后,它仍然无法正常工作,我对VIM一无所知。 - O'Skywalker
显示剩余2条评论
1个回答

2
问题似乎出在模式语法上,特别是结尾处:0 *,)。这个实际上没有什么意义... 修复它似乎解决了大部分问题,虽然我建议放弃DOTALL并改为使用MULTILINE
p = re.compile(ur'([a-zA-Z0-9_]+)::\1(.*\n\W+:.*)(\(UINT\)0,.*)', re.MULTILINE)
sub = u"\\1::\\1\\2\\1\\3"
result = re.sub(p, sub, s)

print(result)

结果:

xdlg::xdlg(x_app* pApp, CWnd* pParent)
    : customized_dlg(xdlg(UINT)0, pParent, pApp)
    , m_pReaderApp(pApp)
    , m_info(pApp)
{

}

https://regex101.com/r/hG3lV7/1


我尝试了你的模式,它确实有效。但是,我很困惑,是否有必要引入5个组?是否可能用2个组解决这个问题? - O'Skywalker
1
不需要五个组(请参见编辑),尽管我也无法完全理解你所拥有的那些组。在我看来,除非您有许多需要跨多个替换进行跟踪的组,否则Python中的命名组有点毫无意义。否则,它只是更多的代码,实际上使事情更加混乱。 - l'L'l
1
不是必要的,所以请将其删除。我认为模式还可以进一步改进——在这种情况下,答案主要是为了说明它不能正常工作的问题。 - l'L'l
我如何使用re.DOTALL达到相同的效果? - O'Skywalker
re.DOTALL 应该与上面的模式配合使用(仍然使用三个捕获组),尽管可以简化为类似于 ([a-zA-Z0-9_]+)::\1(.*)(\(UINT\)0,.*) 的形式。 - l'L'l
让我们在聊天中继续这个讨论 - O'Skywalker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接