Получение sub-match_results с boost :: regex - PullRequest
4 голосов
/ 25 апреля 2011

Эй, допустим, у меня есть это регулярное выражение: (test[0-9])+

И с которым я сопоставляю: test1test2test3test0

const bool ret = boost::regex_search(input, what, r);

for (size_t i = 0; i < what.size(); ++i)
    cout << i << ':' << string(what[i]) << "\n";

Теперь what[1] будет test0(последнее вхождение).Допустим, мне нужно также получить test1, 2 и 3: что мне делать?

Примечание: реальное регулярное выражение чрезвычайно сложное и должно оставаться в общем совпадении, поэтому измените примерное регулярное выражениена (test[0-9]) не будет работать.

Ответы [ 3 ]

10 голосов
/ 26 апреля 2011

Я думаю, что Dot Net имеет возможность создавать коллекции коллекций с одним захватом, так что (grp) + создаст объект коллекции на group1. Regex_search () движка Boost будет похожа на любую обычную функцию соответствия. Вы сидите в цикле while (), совпадающем с шаблоном, где остановилось последнее совпадение. Форма, которую вы использовали, не использует bid-itterator, поэтому функция не начнет следующий матч, где закончился последний матч.

Вы можете использовать форму итератора:
( Редактировать - вы также можете использовать токен-итератор, определяющий, над какими группами итерировать. Добавлено в коде ниже).

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

using namespace std;
using namespace boost;

int main() 
{ 
    string input = "test1 ,, test2,, test3,, test0,,";
    boost::regex r("(test[0-9])(?:$|[ ,]+)");
    boost::smatch what;

    std::string::const_iterator start = input.begin();
    std::string::const_iterator end   = input.end();

    while (boost::regex_search(start, end, what, r))
    {
        string stest(what[1].first, what[1].second);
        cout << stest << endl;
        // Update the beginning of the range to the character
        // following the whole match
        start = what[0].second;
    }

    // Alternate method using token iterator 
    const int subs[] = {1};  // we just want to see group 1
    boost::sregex_token_iterator i(input.begin(), input.end(), r, subs);
    boost::sregex_token_iterator j;
    while(i != j)
    {
       cout << *i++ << endl;
    }

    return 0;
}

Выход:

test1
test2
test3
test0

6 голосов
/ 25 апреля 2011

Boost.Regex предлагает экспериментальную поддержку именно этой функции (называемой повторными захватами);однако, поскольку производительность сильно снижается, эта функция по умолчанию отключена.

Чтобы включить повторные захваты, необходимо перестроить Boost.Regex и определить макрос BOOST_REGEX_MATCH_EXTRA во всех единицах перевода;лучший способ сделать это - раскомментировать это определение в boost / regex / user.hpp (см. ссылку , это в самом низу страницы).

После компиляции с этимопределите, вы можете использовать эту функцию, вызывая / используя regex_search, regex_match и regex_iterator с флагом match_extra.

Проверьте ссылку на Boost.Regex для получения дополнительной информации.

3 голосов
/ 25 апреля 2011

Мне кажется, что вам нужно создать regex_iterator , используя регулярное выражение (test[0-9]) в качестве входных данных. Затем вы можете использовать полученный regex_iterator для перечисления соответствующих подстрок вашей исходной цели.

Если вам все еще нужно «одно общее совпадение», то, возможно, эта работа должна быть отделена от задачи поиска подходящих подстрок. Можете ли вы уточнить эту часть вашего требования?

...