使用std::regex_replace从替换模式引用整个匹配

Referring to whole match from replacement pattern using std::regex_replace

本文关键字:引用 模式 regex std replace 使用 替换      更新时间:2023-10-16

下面的代码在Visual Studio 2015和IDEOne.com (c++ 14)中不会给出相同的结果。更奇怪的是,这两种情况的结果都不正确!

#include <iostream>
#include <regex>
int main()
{
   const char* pszTestString = "ENDRESS+HAUSER*ST-DELL!HP||BESTMATCH&&ABCD\ABCD";
   const char* pszExpectedString = "ENDRESS\+HAUSER\*ST\-DELL\!HP\||BESTMATCH\&&ABCD\\ABCD";
   std::cout << std::regex_replace(pszTestString, std::regex("[-+!"\[\](){}^~*?:]|&&|\|\|"), "\$0") << std::endl;
   std::cout << pszExpectedString << std::endl;
   return 0;
}

在Visual Studio 2015下,我得到了这个奇怪的结果,第二行包含两个编译器的预期结果:

ENDRESS$0HAUSER$0ST$0DELL$0HP$0BESTMATCH$0ABCDABCD
ENDRESS+HAUSER*ST-DELL!HP||BESTMATCH&&ABCD\ABCD

With IDEOne (c++ 14编译器):

ENDRESS+HAUSER*ST-DELL!HP||BESTMATCH&&ABCDABCD
ENDRESS+HAUSER*ST-DELL!HP||BESTMATCH&&ABCD\ABCD

我们可以看到后面有一个错误:在最后一个"ABCD"之前必须有两个反斜杠,而不是一个

这到底是怎么回事?我写了一个手动解析器,而不是使用std::regex_replace,但我真的想让它在VS2015下工作(以及任何其他理想的IDE),并在选择手动解析解决方案之前做一个基准测试。

VS2015默认编译器不将$0视为第零反向引用。你需要使用"native" ECMAScript $&反向引用从替换模式内部引用整个匹配

此外,revo是正确的,为了匹配,您需要将其添加到字符类。

请注意,在VS2015中可以使用原始字符串字面值。最佳实践是使用原始字符串字面值来定义正则表达式模式,因为它们有助于避免过度转义(也称为反斜杠地狱)。

解决方案:

std::cout << std::regex_replace(pszTestString, 
      std::regex(R"([-+!\"[](){}^~*?:]|&&|||)"), "\$&") << std::endl;
                        ^^                                ^^