【问题标题】:std::regex_replace replace n occurences and get number of substitutionsstd::regex_replace 替换 n 次出现并获取替换次数
【发布时间】:2014-12-28 20:57:10
【问题描述】:

我正在使用 std::regex_replace 来修改字符串。我既需要限制替换,又需要完成替换次数。

我使用了以下代码:

std::wregex rx(pattern);
size_t n = 0; // one match
size_t ns = 3;
wstring result = src;
wstring old; // old value
bool replaced = false;

do {
    old = result;
    result = std::regex_replace(result, rx, replace, std::regex_constants::format_first_only);
    replaced = result != old;
    if (replaced)
        n++;
} while (replaced && n < ns); 

效果很好,我既可以限制替代品的数量,也可以获取它们的数量。但是,如果我有以下值,这段代码会从一开始就分析字符串:

"banana" for src, "(an)" for pattern and "$1-" for replace

它产生以下输出:ban---ana 而不是 ban-an-a。显然,这是因为 std::regex_replace 从一开始就分析字符串。一种解决方案可能是使用迭代器来定义要分析的第一个字符,但在这种情况下,我需要获取指向被替换后的字符的迭代器,但我怎样才能得到它?

【问题讨论】:

  • 你很幸运,因为std::regex_replace 有两个重载可以满足你的需要,即处理迭代器而不是字符串,包括返回一个迭代器。
  • 我知道这种重载,但你能举个例子吗?
  • 基本上你要替换同样的东西 3 次。这就是您收到ban---ana 的原因。由于您每次都从字符串的开头开始传递一个字符串。但是,还有另一种方法。

标签: c++ regex c++11 std


【解决方案1】:

事实证明这比我想象的要棘手。我没有发现任何 std::regex_replace() 函数在这里很有帮助。

我决定根据此处实施描述中建议的算法直接使用std::wsregex_iterator 解决方案:

http://en.cppreference.com/w/cpp/regex/regex_replace

这是我想出的:

#include <regex>
#include <string>
#include <iterator>
#include <iostream>

int main()
{
    std::size_t ns = 3;
    std::wstring text = L"banana";
    std::wstring pattern = L"(an)";
    std::wstring replace = L"$1-";
    std::wstring result;

    std::wregex rx(pattern);

    auto iter = std::wsregex_iterator(text.begin(), text.end(), rx);
    auto stop = std::wsregex_iterator();
    auto last_iter = iter;

    auto out = std::back_inserter(result);

    for(std::size_t n = ns; n-- && iter != stop; ++iter)
    {
        out = std::copy(iter->prefix().first, iter->prefix().second, out);
        out = iter->format(out, replace);
        last_iter = iter;
    }

    out = std::copy(last_iter->suffix().first, last_iter->suffix().second, out);

    std::wcout << "  text: " << text << '\n';
    std::wcout << "result: " << result << '\n';
}

输出:

  text: banana
result: ban-an-a

【讨论】:

    【解决方案2】:

    您可以设置计数器并使用回调。这只会替换您设置的最大值。
    (未经测试)

    static int REPL_count = 0;
    static int REPL_max = 0;
    static string REPL_replace = "";
    
    
    string REPLcallback( const wsmatch m )
    {
        // Return formatted match if under the max count
        if ( REPL_count < REPL_max )
        {
            ++REPL_count;
            return m.format( REPL_replace );
        }
        // Exceeded count, just return match without formatting
        return string(m[0].first, m[0].second);
    }
    
    int ReplaceText(
             string& strIn,
             string& strOut,
             wregex  Regex,
             string& strReplacement,
             int     max )
    {
        REPL_count = 0;
        REPL_max = max;
        REPL_replace = strReplacement;
        strOut = regex_replace( strIn, Regex, REPLcallback );
        return REPL_count;
    }
    

    【讨论】:

    • OP 声明他使用 std::regex_replace()。您提供的代码不适用于 std::regex_replace()。 std::regex_replace() 根本没有回调参数。您的建议可能需要 regex_replace() 的增强版本。
    猜你喜欢
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 2018-09-08
    • 1970-01-01
    • 2011-03-05
    相关资源
    最近更新 更多