Как перехватить все совпадения повторяющейся группы с Boost :: regex_search? - PullRequest
5 голосов
/ 28 июня 2010

Я пытаюсь разобрать входную строку с помощью регулярного выражения.У меня проблема при попытке захвата повторяющейся группы.Кажется, я всегда соответствую последнему экземпляру группы.Я пытался использовать Reluctant (не жадные) квантификаторы, но мне кажется, что-то не хватает.Может кто-нибудь помочь?

Попытка регулярного выражения:

(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

Строка ввода:

OS BENKL/LHRBA/MANQFL\r\n

Мне всегда кажется, что я получаю последнюю группу - группу MANQFL (MAN QFL),и моя цель состоит в том, чтобы получить все три группы (может быть 1-5 групп):

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

Фрагмент кода C ++:

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

Этот цикл выполняется только один раз, хотя я ожидаюэто запустить 3 раза в этом примере.Любая помощь будет высоко ценится.

Ответы [ 4 ]

4 голосов
/ 15 июня 2011

Лучший способ получить несколько совпадений из boost :: regex - это использовать regex_iterators.Этот пример должен делать то, что вы хотите.

#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;
}
1 голос
/ 12 июля 2010

Единственный известный мне вариант regex, который может дать вам все итерации группы захвата, - это .NET regex. Обычно механизм регулярных выражений сохраняет только последнюю итерацию каждой группы захвата.

Общим решением проблемы такого рода является использование одного регулярного выражения для захвата всех итераций группы и второго регулярного выражения для разделения результата первого регулярного выражения на отдельные элементы. Алан уже объяснил, как вы можете сделать это в данной конкретной ситуации.

0 голосов
/ 05 августа 2011

Читайте раздел о повторных захватах здесь: http://www.boost.org/doc/libs/1_47_0/libs/regex/doc/html/boost_regex/captures.html

По сути, вам нужна экспериментальная функция, которую можно включить, передав соответствующие #defines и флаги вашему вызову regex_search.

0 голосов
/ 28 июня 2010

Это ожидаемое поведение: когда группа захвата контролируется квантификатором, каждое повторение перезаписывает все, что было записано в предыдущий раз.Самый простой способ получить все совпадения - поместить группу захвата вокруг всего этого, например:

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

Эта группа в конечном итоге будет содержать BENKL/LHRBA/MANQFL, которую вы можете разделить на /.

...