這是指在一次執行中把要替換的多筆字串一次完成,哪組先找到先替換,替換過的不能再被替換。有別於多次執行替換的處理。
關於拿掉 if (!f) return Src; 的原因在,只有 Replacements 為空時才會有作用可提早離開,並不會影響功能的正確性,絕大多數 Replacements 並不會是空的,沒必要多此一舉。
- #include <string>
- #include <functional>
- #include <regex>
- #include <unordered_map>
- #include <iostream>
- using namespace std;
- // 多重字串替換
- class MultipleReplace
- {
- protected:
- static string Regex_MultipleReplace(
- const string &Src,
- const regex &rgx,
- const function<string(const smatch &sm)> &fmt
- )
- {
- string S = Src;
- string R;
- smatch sm;
- while (regex_search(S, sm, rgx))
- {
- R = R + string(S, 0, sm.position()) + fmt(sm);
- S = sm.suffix().str();
- }
- return R + S;
- }
- // 找出字串中含有正則表達式用到的特殊字元,在其前頭加上 '\' 字
- // 元,再將處理完的字串傳回
- // 這段由 AI 生成
- static string addSlashesToRegex(const string &str)
- {
- string specialChars = ".^$*+?()[{\\|";
- string result = "";
- for (int i = 0; i < str.length(); i++)
- {
- if (specialChars.find(str[i]) != string::npos)
- {
- result += "\\";
- }
- result += str[i];
- }
- return result;
- }
- // Constructor
- MultipleReplace (){};
- public:
- // 在一次執行中把要替換的多筆字串一次完成,
- // 哪組先找到先替換,替換過的不能再被替換。
- static string Replace(const string &Src,
- const unordered_map<string, const string>& replacements)
- {
- string rgx;
- bool f = false;
- for (const auto& replacement : replacements)
- {
- if(f)
- rgx += "|";
- rgx += "(" + addSlashesToRegex(replacement.first) + ")";
- f = true;
- }
- // if(!f)
- // return Src;
- return Regex_MultipleReplace(Src,regex(rgx),
- [&replacements](const smatch &sm) -> string
- {
- return const_cast<unordered_map<string, const string>&>(
- replacements)[sm.str()];
- }
- );
- }
- // 為以下這個類別(前一版)增加一個 static 函數,像 Replace()
- // 一樣可以做多重替換,用正則表達式來進行搜索和替換
- // AI 生成人工優化
- static string RegexReplace(const string& Src,
- const unordered_map<string, const string>& replacements)
- {
- string rgx;
- bool f = false;
- for (const auto& replacement : replacements)
- {
- if (f)
- rgx += "|";
- rgx += "(" + replacement.first + ")";
- f = true;
- }
- // if (!f)
- // return Src;
- return Regex_MultipleReplace(Src, regex(rgx),
- [&replacements](const smatch& sm) -> string
- {
- string matchStr = sm.str();
- for (const auto& replacement : replacements)
- {
- regex rgx(replacement.first);
- if (regex_match(matchStr, rgx))
- {
- return replacement.second;
- }
- }
- return matchStr;
- }
- );
- }
- // 融合 Replace() 和 RegexReplace()
- // directReplacements 直接字元搜尋替換,regexReplacements 正則表達式搜尋替換
- // 符合的搜尋 directReplacements 優先於 regexReplacements
- // 一樣一次執行中把要替換的多筆字串一次完成,哪組先找到先替換,替換過的不能再被替換
- static string MixReplace(const string& Src,
- const unordered_map<string, const string>& directReplacements,
- const unordered_map<string, const string>& regexReplacements)
- {
- string rgx;
- bool f = false;
- for (const auto& replacement : directReplacements)
- {
- if(f)
- rgx += "|";
- rgx += "(" + addSlashesToRegex(replacement.first) + ")";
- f = true;
- }
- for (const auto& replacement : regexReplacements)
- {
- if (f)
- rgx += "|";
- rgx += "(" + replacement.first + ")";
- f = true;
- }
- // if (!f)
- // return Src;
- return Regex_MultipleReplace(Src, regex(rgx),
- [&directReplacements,®exReplacements](const smatch& sm) -> string
- {
- string matchStr = sm.str();
- string result = const_cast<unordered_map<string, const string>&>(
- directReplacements)[matchStr];
- if(!result.empty())
- return std::move(result);
- for (const auto& replacement : regexReplacements)
- {
- regex rgx(replacement.first);
- if (regex_match(matchStr, rgx))
- {
- return replacement.second;
- }
- }
- return std::move(matchStr);
- }
- );
- }
- };
- // 請用 C++11 用以上的功能在 main() 分別為 Replace()、RegexReplace()
- // 和 MixReplace() 寫一個例子。要列印出例子的用意和替換前後的字串,其
- // 中用來 {搜尋,替換} 的組數須不一樣,但須在 2 至 10 組之間,同時讓我看到輸出結果
- // AI 生成
- int main() {
- // 用 Replace() 進行字串替換
- std::cout << "Use Replace() to replace multiple strings:" << std::endl;
- std::string str1 = "Replace AAA, BBB and CCC with X, Y and Z";
- std::cout << "Before: " << str1 << std::endl;
- std::unordered_map<std::string, const std::string> replacements1 = {
- {"AAA", "X"},
- {"BBB", "Y"},
- {"CCC", "Z"}
- };
- str1 = MultipleReplace::Replace(str1, replacements1);
- std::cout << "After: " << str1 << std::endl;
- std::cout << std::endl;
- // 用 RegexReplace() 進行字串替換
- std::cout <<
- "Use RegexReplace() to replace multiple strings with regex:"
- << std::endl;
- std::string str2 = "Replace AAA, BBB and CCC with X, Y and Z using regex";
- std::cout << "Before: " << str2 << std::endl;
- std::unordered_map<std::string, const std::string> replacements2 = {
- {"AAA", "X"},
- {"\\bBBB\\b", "Y"},
- {"C+", "Z"}
- };
- str2 = MultipleReplace::RegexReplace(str2, replacements2);
- std::cout << "After: " << str2 << std::endl;
- std::cout << std::endl;
- // 用 MixReplace() 進行字串替換
- std::cout <<
- "Use MixReplace() to replace multiple strings with both direct and regex:"
- << std::endl;
- std::string str3 =
- "Replace AAA, BBB and CCC with X, Y and Z using both direct and regex";
- std::cout << "Before: " << str3 << std::endl;
- std::unordered_map<std::string, const std::string> directReplacements = {
- {"AAA", "X"},
- {"BBB", "Y"}
- };
- std::unordered_map<std::string, const std::string> regexReplacements = {
- {"\\bCCC\\b", "Z"},
- {"using.*regex", "with regex"}
- };
- str3 = MultipleReplace::MixReplace(str3, directReplacements,
- regexReplacements);
- std::cout << "After: " << str3 << std::endl;
- return 0;
- }
輸出結果:
Use Replace() to replace multiple strings:
Before: Replace AAA, BBB and CCC with X, Y and Z
After: Replace X, Y and Z with X, Y and Z
Use RegexReplace() to replace multiple strings with regex:
Before: Replace AAA, BBB and CCC with X, Y and Z using regex
After: Replace X, Y and Z with X, Y and Z using regex
Use MixReplace() to replace multiple strings with both direct and regex:
Before: Replace AAA, BBB and CCC with X, Y and Z using both direct and regex
After: Replace X, Y and Z with X, Y and Z with regex
沒有留言:
張貼留言