我在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);
对我来说没有意义......
答案 0 :(得分:3)
正则表达式中存在一个微妙的错误。不要忘记编译器会扩展字符串文字中的转义序列。所以改变
"http://([^@:/]+\.)?wik(ipedia|imedia)\.org/"
到
"http://([^@:/]+\\.)?wik(ipedia|imedia)\\.org/"
也就是说,用一对反斜杠替换两个单反斜杠中的每一个。
编辑:但这似乎并没有影响到这个问题。在我尝试的两个实现中(微软和clang),原始问题不会发生,我们没有加倍的反斜杠。 (没有,您会收到有关无效转义序列的编译器警告,但生成的.
通配符与目标序列中的.
字符匹配,就像\.
那样)