std::regex equivalent of '/g' global modifier
Asked Answered
O

1

8

In Perl, I can do this:

$text = '1747239';
@matches = ($text =~ m/(\d)/g);
# @matches now contains ('1', '7', '4', '7', '2', '3', '9')

Using C++ regex matching, what's the best way to replicate this behaviour so that I get a match set including all the matches?

I have this at the moment:-

compiledRegex = std::regex(regex, std::tr1::regex_constants::extended);
regex_search(text, results, compiledRegex);

int count = results.size();
// Alloc pointer array based on count * sizeof(mystruct).
for ( std::cmatch::iterator match = results.begin(); 
      match != results.end(); 
      ++match )
{
    // Do something with match;
}

However this will only give me the first match, just like Perl without the /g which is fine, but I'd like the /g effect.

So, is there a good way to do it, or must I keep running the regex over and over?

Overfill answered 26/5, 2011 at 9:54 Comment(0)
S
14

You should call regex_search several times. Its return value specifies whether there are more matches. Each time you call it you get a new match. The iterator returned by results goes over the group submatches defined in your regular expression. The first entry is always the entire match, that's why in your case count == 1

std::string::const_iterator text_iter = text.cbegin();
compiledRegex = std::regex(regex, std::tr1::regex_constants::extended);

while (regex_search(text_iter, text.end(), results, compiledRegex))
{
    int count = results.size();
    // Alloc pointer array based on count * sizeof(mystruct).
    for ( std::cmatch::iterator group = results.begin();
          group != results.end();
          ++group )
    {
        // If you uses grouping in your search here you can access each group
    }

   std::cout << std::string(results[0].first, results[0].second) << endl;
   text_iter = results[0].second;
}

Hope it helps

Surgery answered 26/5, 2011 at 11:38 Comment(2)
That's pretty much what I was winding up with, I guess I was hoping for a flag to make regex_search do it. Presumably you need to move the text pointer on to the end of the last match on each iteration?Overfill
@JonB You are right. The iterators instead of string should be used. At the end of each iteration, the search iterator should be updated, using results[0].second. I've updated my answer corespodingly.Surgery

© 2022 - 2024 — McMap. All rights reserved.