Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I capture all matches of a repeating group with Boost::regex_search?

I am trying to parse an input string using a regular expression. I am getting a problem when trying to capture a repeating group. I always seem to be matching last instance of the group. I have tried using Reluctant (non greedy) quantifiers, but I seems to be missing something. Can someone help?

Regular expression tried:

(OS)\\s((\\w{3})(([A-Za-z0-9]{2})|(\\w{3})(\\w{3}))\\/{0,1}){1,5}?\\r

(OS)\\s((\\w{3}?)(([A-Za-z0-9]{2}?)|(\\w{3}?)(\\w{3}?))\\/{0,1}?){1,5}?\\r

Input String:

OS BENKL/LHRBA/MANQFL\r\n

I always seem to get last group which is MANQFL group (MAN QFL), and my aim is to get all three groups (there can be 1-5 groups):

(BEN KL) , (LHR BA) and (MAN QFL). 

C++ code snippet:

std::string::const_iterator start = str.begin(), end = str.end(); 
while(regex_search(start,end,what,expr)) 
{ 
  cout << what[0]; 
  cout << what[1]; 
  ... 
  start += what.position () + what.length (); 
}

This loop only exceutes once, while I expect it to run 3 times in this example. Any help will be much appreciated.

like image 692
omshanti Avatar asked Jun 28 '10 15:06

omshanti


People also ask

How do you repeat a capturing group in regex?

"Capturing a repeated group captures all iterations." In your regex101 try to replace your regex with (\w+),? and it will give you the same result. The key here is the g flag which repeats your pattern to match into multiple groups.


2 Answers

The best way of getting multiple matches out of boost::regex is to use regex_iterators. This example should do what you want.

#include <iostream>
#include <string>
#include <boost/regex.hpp>

int main() {
    std::string a = "OS BENKL/LHRBA/MANQFL\r\n";
    const boost::regex re("[A-Z]{3}[A-Z]*");
    boost::sregex_iterator res(a.begin(),a.end(),re);
    boost::sregex_iterator end;
    for (; res != end; ++res)
        std::cout << (*res)[0] << std::endl;
}
like image 136
Marty B Avatar answered Oct 30 '22 13:10

Marty B


The only regex flavor that I know that can give you all the iterations of a capturing group is the .NET regex flavor. Normally a regex engine only saves the last iteration of each capturing group.

The general solution to this kind of problem is to use one regex to capture all the iterations of the group, and a second regex to split the result of the first regex into the separate items. Alan already explained how you can do this in this particular situation.

like image 1
Jan Goyvaerts Avatar answered Oct 30 '22 13:10

Jan Goyvaerts