正则表达式替换为 c++11 中的回调?

2022-01-03 00:00:00 regex callback c++ c++11

是否有正则表达式替换功能,将匹配发送到用户函数,然后替换返回值:

Is there a function of regex replacement that will send the matches to user function and then substitute the return value:

这个方法我试过了,但显然不行:

I've tried this method, but it obviously doesn't work:

cout << regex_replace("my values are 9, 19", regex("d+"), my_callback);

和功能:

std::string my_callback(std::string &m) {
  int int_m = atoi(m.c_str());
  return std::to_string(int_m + 1);
}

结果应该是:my values are 10, 20

我的意思是类似于 php 的 preg_replace_callback 或 python 的 re.sub(pattern, callback, subject)

I mean similar mode of working like php's preg_replace_callback or python's re.sub(pattern, callback, subject)

我的意思是最新的 4.9 gcc,它能够在没有 boost 的情况下进行正则表达式.

And I mean the latest 4.9 gcc, that is capable of regex without boost.

推荐答案

我想要这种功能,但不喜欢使用 boost"这个答案.Benjamin 的答案的问题在于它提供了所有的令牌.这意味着您不知道哪个令牌是匹配的,并且它不允许您使用捕获组.这样做:

I wanted this kind of function and didn't like the answer "use boost". The problem with Benjamin's answer is it provides all the tokens. This means you don't know which token is a match and it doesn't let you use capture groups. This does:

// clang++ -std=c++11 -stdlib=libc++ -o test test.cpp
#include <cstdlib>
#include <iostream>
#include <string>
#include <regex>

namespace std
{

template<class BidirIt, class Traits, class CharT, class UnaryFunction>
std::basic_string<CharT> regex_replace(BidirIt first, BidirIt last,
    const std::basic_regex<CharT,Traits>& re, UnaryFunction f)
{
    std::basic_string<CharT> s;

    typename std::match_results<BidirIt>::difference_type
        positionOfLastMatch = 0;
    auto endOfLastMatch = first;

    auto callback = [&](const std::match_results<BidirIt>& match)
    {
        auto positionOfThisMatch = match.position(0);
        auto diff = positionOfThisMatch - positionOfLastMatch;

        auto startOfThisMatch = endOfLastMatch;
        std::advance(startOfThisMatch, diff);

        s.append(endOfLastMatch, startOfThisMatch);
        s.append(f(match));

        auto lengthOfMatch = match.length(0);

        positionOfLastMatch = positionOfThisMatch + lengthOfMatch;

        endOfLastMatch = startOfThisMatch;
        std::advance(endOfLastMatch, lengthOfMatch);
    };

    std::regex_iterator<BidirIt> begin(first, last, re), end;
    std::for_each(begin, end, callback);

    s.append(endOfLastMatch, last);

    return s;
}

template<class Traits, class CharT, class UnaryFunction>
std::string regex_replace(const std::string& s,
    const std::basic_regex<CharT,Traits>& re, UnaryFunction f)
{
    return regex_replace(s.cbegin(), s.cend(), re, f);
}

} // namespace std

using namespace std;

std::string my_callback(const std::smatch& m) {
  int int_m = atoi(m.str(0).c_str());
  return std::to_string(int_m + 1);
}

int main(int argc, char *argv[])
{
    cout << regex_replace("my values are 9, 19", regex("\d+"),
        my_callback) << endl;

    cout << regex_replace("my values are 9, 19", regex("\d+"),
        [](const std::smatch& m){
            int int_m = atoi(m.str(0).c_str());
            return std::to_string(int_m + 1);
        }
    ) << endl;

    return 0;
}

相关文章