std :: regex_replace给了我意想不到的结果

时间:2012-12-20 18:14:48

标签: c++ regex windows c++11

我在C ++ Windows项目中使用std::regex_replace(Visual Studio 2010)。代码如下所示:

std::string str("http://www.wikipedia.org/");
std::regex fromRegex("http://([^@:/]+\\.)?wik(ipedia|imedia)\\.org/", std::regex_constants::icase);
std::string fmt("https://$1wik$2.org/");
std::string result = std::regex_replace(str, fromRegex, fmt);

我希望result"https://www.wikipedia.org/",但我得到"https://www.wikipedia.wikipedia.org/"

使用sed进行快速检查可以获得预期结果

$ cat > test.txt
http://www.wikipedia.org/
$ sed 's/http:\/\/([^@:\/]+\.)?wik(ipedia|imedia)\.org\//https:\/\/$1wik$2.org\//' test.txt
http://www.wikipedia.org/

我不知道差异来自哪里。我检查了可以与std::regex_replace一起使用的标志,我没有看到在这种情况下有用的标志。

更新

这些变体很好用:

std::regex fromRegex("http://([^@:/]+\\.)wik(ipedia|imedia)\\.org/", std::regex_constants::icase);
std::regex fromRegex("http://((?:[^@:/]+\\.)?)wik(ipedia|imedia)\\.org/", std::regex_constants::icase);
std::regex fromRegex("http://([a-z]+\\.)?wik(ipedia|imedia)\\.org/", std::regex_constants::icase);
std::regex fromRegex("http://([^a]+\\.)?wik(ipedia|imedia)\\.org/", std::regex_constants::icase);

不是这些:

std::regex fromRegex("http://([^1-9]+\\.)?wik(ipedia|imedia)\\.org/", std::regex_constants::icase);
std::regex fromRegex("http://([^@]+\\.)?wik(ipedia|imedia)\\.org/", std::regex_constants::icase);
std::regex fromRegex("http://([^:]+\\.)?wik(ipedia|imedia)\\.org/", std::regex_constants::icase);

对我来说没有意义......

1 个答案:

答案 0 :(得分:3)

正则表达式中存在一个微妙的错误。不要忘记编译器会扩展字符串文字中的转义序列。所以改变

"http://([^@:/]+\.)?wik(ipedia|imedia)\.org/"

"http://([^@:/]+\\.)?wik(ipedia|imedia)\\.org/"

也就是说,用一对反斜杠替换两个单反斜杠中的每一个。

编辑:但这似乎并没有影响到这个问题。在我尝试的两个实现中(微软和clang),原始问题不会发生,我们没有加倍的反斜杠。 (没有,您会收到有关无效转义序列的编译器警告,但生成的.通配符与目标序列中的.字符匹配,就像\.那样)