Как сопоставить несколько результатов с помощью std:: regex
например. Если у меня есть строка, подобная "первая секунда четвертая четвертая", и я хочу сопоставить каждое отдельное слово в одной операции для вывода "один за другим".
Я просто подумал, что "(\ b\S *\b) {0,}" будет работать. Но на самом деле это не так.
Что мне делать?
Здесь мой код:
#include<iostream>
#include<string>
using namespace std;
int main()
{
regex exp("(\\b\\S*\\b)");
smatch res;
string str = "first second third forth";
regex_search(str, res, exp);
cout << res[0] <<" "<<res[1]<<" "<<res[2]<<" "<<res[3]<< endl;
}
Я с нетерпением жду вашей любезной помощи.:)
Ответы
Ответ 1
Это можно сделать в regex
C++11
.
Два метода:
-
Вы можете использовать ()
в regex
для определения ваших захватов.
Вот так:
string var = "first second third forth";
const regex r("(.*) (.*) (.*) (.*)");
smatch sm;
if (regex_search(var, sm, r))
{
for (int i=1; i<sm.size(); i++)
{
cout << sm[i] << endl;
}
}
Смотрите в прямом эфире: http://coliru.stacked-crooked.com/a/e1447c4cff9ea3e7
-
Вы можете использовать sregex_token_iterator()
:
string var = "first second third forth";
regex wsaq_re("\\s+");
copy( sregex_token_iterator(var.begin(), var.end(), wsaq_re, -1),
sregex_token_iterator(),
ostream_iterator<string>(cout, "\n"));
Смотрите это в прямом эфире: http://coliru.stacked-crooked.com/a/677aa6f0bb0612f0
Ответ 2
Вы можете использовать функцию suffix() и искать снова, пока не найдете совпадения:
int main()
{
regex exp("(\\b\\S*\\b)");
smatch res;
string str = "first second third forth";
while (regex_search(str, res, exp)) {
cout << res[0] << endl;
str = res.suffix();
}
}
Ответ 3
Просто перебирайте строку во время regex_searching, например:
{
regex exp("(\\b\\S*\\b)");
smatch res;
string str = "first second third forth";
string::const_iterator searchStart( str.cbegin() );
while ( regex_search( searchStart, str.cend(), res, exp ) )
{
cout << ( searchStart == str.cbegin() ? "" : " " ) << res[0];
searchStart += res.position() + res.length();
}
cout << endl;
}
Ответ 4
не стесняйтесь использовать мой код. Он будет захватывать все группы во всех матчах:
vector<vector<string>> U::String::findEx(const string& s, const string& reg_ex, bool case_sensitive)
{
regex rx(reg_ex, case_sensitive ? regex_constants::icase : 0);
vector<vector<string>> captured_groups;
vector<string> captured_subgroups;
const std::sregex_token_iterator end_i;
for (std::sregex_token_iterator i(s.cbegin(), s.cend(), rx);
i != end_i;
++i)
{
captured_subgroups.clear();
string group = *i;
smatch res;
if(regex_search(group, res, rx))
{
for(unsigned i=0; i<res.size() ; i++)
captured_subgroups.push_back(res[i]);
if(captured_subgroups.size() > 0)
captured_groups.push_back(captured_subgroups);
}
}
captured_groups.push_back(captured_subgroups);
return captured_groups;
}
Ответ 5
Мое чтение документации заключается в том, что regex_search
выполняет поиск первого совпадения и что ни одна из функций из std::regex
не выполняет "сканировать", как вы ищите. Тем не менее, библиотека Boost, похоже, поддерживает это, как описано в С++, чтобы токенизировать строку, используя регулярное выражение