2

std::regex_replace在 C++ Windows 项目(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);

对我来说完全是无稽之谈...

4

1 回答 1

3

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

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

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

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

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

于 2012-12-20T19:39:47.073 回答