2

std::regex_replaceC++ 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/"

つまり、2つの単一の円記号のそれぞれを1対の円記号に置き換えます。

編集:しかし、これは問題に影響を与えていないようです。私が試した2つの実装(Microsoftとclang)では、元の問題は発生せず、バックスラッシュが2倍になっています。(これがないと、無効なエスケープシーケンスに関するコンパイラの警告が表示されますが、結果の.ワイルドカード.は、ターゲットシーケンスの文字と同じように一致します\.

于 2012-12-20T19:39:47.073 に答える