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

4

6

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.

Ehman answered 28/6, 2010 at 15:18 Comment(2)
It would help a lot if you'd tell us more about the format of the input, and how you want it parsed.Chatter
Input is the string stream, and in this example I expect to get 3 groups (BEN KL) , (LHR BA) and (MAN QFL). I know in this case we can do it even without using regular expressions, but I am just trying to see if I can keep it consistent with the existing code where regex is used.Ehman
L
5

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;
}
Lesslie answered 14/6, 2011 at 23:9 Comment(0)
S
1

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.

Submicroscopic answered 12/7, 2010 at 8:5 Comment(0)
S
0

That's the expected behavior: when a capturing group is controlled by a quantifier, each repetition overwrites whatever was captured the previous time. The simplest way to get all of the matches would be to put a capturing group around the whole thing, like this:

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

That group will end up containing BENKL/LHRBA/MANQFL, which you can split on the /.

Spinner answered 28/6, 2010 at 17:55 Comment(0)
S
0

Read the section about repeated captures here: http://www.boost.org/doc/libs/1_47_0/libs/regex/doc/html/boost_regex/captures.html

Basically, what you want is an experimental feature that can be enabled by passing the appropriate #defines and flags to your regex_search call.

Stirrup answered 5/8, 2011 at 17:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.