std::regex_replace用于替换多个组合

huangapple go评论76阅读模式
英文:

std::regex_replace to replace multiple combinations

问题

我尝试使用std::regex_replace来替换一些字符组合为其他字符。然而,每组字符都有不同的替换字符(这取决于字符)。我考虑使用map,但由于我无法访问要替换的字符(如代码中所示),这种方法不起作用。有没有办法在一个regex_replace语句中涵盖所有替换情况(或者也许有更好的方法)?
现有代码:

std::regex r(" c|ph|th|ea|c|w");
map<string, string> comb{
	{" c", "k"},
	{"ph", "f"},
	{"th", "z"},
	{"ea", "e"},
	{"c", "s"},
	{"w", "v"}
};
line = std::regex_replace(line, r, comb[r]);
英文:

I am trying to utilize the std::regex_replace to replace a few combinations of characters with other characters. However, each set of characters has a different set of characters I would like to replace it with (it depends on the character).
I thought about using a map , but that will not work as I do not have access to the character being replaced (as seen in the code). Any idea how to cover all replacement cases in one regex_replace statement (or perhaps a better approach) ?
Current Code:

std::regex r(&quot; c|ph|th|ea|c|w&quot;);
	map&lt;string, string&gt; comb{
		{&quot; c&quot;, &quot;k&quot;},
		{ &quot;ph&quot;, &quot;f&quot; },	
		{ &quot;th&quot;, &quot;z&quot; },
		{ &quot;ea&quot;, &quot;e&quot; },
		{ &quot;c&quot;, &quot;s&quot; },
		{ &quot;w&quot;, &quot;v&quot; }
	};
line = std::regex_replace(line, r, comb[r]);

答案1

得分: 1

我们可以使用regex_iterator和您的映射一起自定义regex_replace函数:

演示示例

首先,让我们编写一个函数,该函数接受一个std::map&lt;string, string&gt;并返回一个正则表达式,该表达式只是键之间的替代 |。这将允许我们在映射和生成的正则表达式之间保持强大的关联。

std::regex regex_from_map(const std::map&lt;std::string, std::string&gt;&amp; map)
{
    std::string pattern_str = &quot;(&quot;;
    auto it = map.begin();
    if (it != map.end())
    {
        pattern_str += it-&gt;first;
        for(++it; it != map.end(); ++it)
            pattern_str += &quot;|&quot; + it-&gt;first;
    }
    pattern_str += &quot;)&quot;;
    return std::regex(pattern_str);
}

接下来,让我们编写一个函数,该函数接受要匹配的文本和您的替换映射,然后迭代每个匹配并找到适当的替换以构建结果字符串:

std::string custom_regex_replace(const std::string&amp; text,
    const std::map&lt;std::string, std::string&gt;&amp; replacement_map)
{
    auto regex = regex_from_map(replacement_map);
    std::string result;
    std::sregex_iterator it(text.begin(), text.end(), regex);
    std::sregex_iterator end;

    size_t last_pos = 0;
    for (; it != end; ++it) {
        result += text.substr(last_pos, it-&gt;position() - last_pos);
        result += replacement_map.at(it-&gt;str());
        last_pos = it-&gt;position() + it-&gt;length();
    }
    result += text.substr(last_pos, text.size() - last_pos);

    return result;
}

最后,调用我们的自定义替换函数:

int main() {
    std::map&lt;std::string, std::string&gt; replacement_map = 
    {   {&quot; c&quot;, &quot;k&quot;},
        { &quot;ph&quot;, &quot;f&quot; },  
        { &quot;th&quot;, &quot;z&quot; },
        { &quot;ea&quot;, &quot;e&quot; },
        { &quot;c&quot;, &quot;s&quot; },
        { &quot;w&quot;, &quot;v&quot; }
    };

    std::string text = &quot;each word pheels new, cnow?&quot;;
    std::string new_text = custom_regex_replace(text, replacement_map);
    std::cout &lt;&lt; new_text &lt;&lt; std::endl;

    return 0;
}

输入:
> "each word pheels new, cnow?"

输出:
> "esh vord feels nev,knov?"

(请注意&quot; c&quot;被替换为&quot;k&quot;,所以逗号后的空格被删除)

英文:

We can hack together our own custom regex_replace using a regex_iterator and your map:

Live Demo

First, let's write function that accepts a std::map&lt;string, string&gt; and returns a regex that is just an alternation | between the keys. This will let us keep a strong association between the map and the resulting regex.

std::regex regex_from_map(const std::map&lt;std::string, std::string&gt;&amp; map)
{
    std::string pattern_str = &quot;(&quot;;
    auto it = map.begin();
    if (it != map.end())
    {
        pattern_str += it-&gt;first;
        for(++it; it != map.end(); ++it)
            pattern_str += &quot;|&quot; + it-&gt;first;
    }
    pattern_str += &quot;)&quot;;
    return std::regex(pattern_str);
}

Next, let's write a function that accepts the text to be matched and your replacement map, then iterates over each match and finds the appropriate replacement to build the result string:

std::string custom_regex_replace(const std::string&amp; text,
    const std::map&lt;std::string, std::string&gt;&amp; replacement_map)
{
    auto regex = regex_from_map(replacement_map);
    std::string result;
    std::sregex_iterator it(text.begin(), text.end(), regex);
    std::sregex_iterator end;

    size_t last_pos = 0;
    for (; it != end; ++it) {
        result += text.substr(last_pos, it-&gt;position() - last_pos);
        result += replacement_map.at(it-&gt;str());
        last_pos = it-&gt;position() + it-&gt;length();
    }
    result += text.substr(last_pos, text.size() - last_pos);

    return result;
}

Finally, calling our custom replacement function:

int main() {
    std::map&lt;std::string, std::string&gt; replacement_map = 
    {   {&quot; c&quot;, &quot;k&quot;},
        { &quot;ph&quot;, &quot;f&quot; },  
        { &quot;th&quot;, &quot;z&quot; },
        { &quot;ea&quot;, &quot;e&quot; },
        { &quot;c&quot;, &quot;s&quot; },
        { &quot;w&quot;, &quot;v&quot; }
    };

    std::string text = &quot;each word pheels new, cnow?&quot;;
    std::string new_text = custom_regex_replace(text, replacement_map);
    std::cout &lt;&lt; new_text &lt;&lt; std::endl;

    return 0;
}

Input:
> "each word pheels new, cnow?"

Output:
> "esh vord feels nev,knov?"

(Note that &quot; c&quot; is replace with &quot;k&quot;, so the space after the comma was deleted)

huangapple
  • 本文由 发表于 2023年3月21日 00:09:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/75792695.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定