Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

regex replace with callback in c++11?

Tags:

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); 

and function:

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

and the result should be: my values are 10, 20

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

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

like image 817
rsk82 Avatar asked Mar 24 '14 18:03

rsk82


1 Answers

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; } 
like image 113
John Martin Avatar answered Oct 21 '22 04:10

John Martin