Хотя уже есть принятый ответ, я хотел бы показать очень простое и простое решение. Протестировано с C ++ 17. И полный исходный код.
Поскольку речь идет о макс. 7 группах, мы можем просто перечислить их все и «или» их. Это может быть много текста и сложный DFA. Но это должно сработать.
После того, как мы нашли совпадение, мы определяем вектор, помещаем в него все данные / группы и показываем желаемый результат. Это действительно просто:
Пожалуйста, смотрите:
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <regex>
std::vector<std::string> test{
"X::Y",
"X:X::Y",
"X:X::Y:Y",
"X:X:X::Y:Y",
"X::Y:Y:Y:Y:Y",
"X:X:X:X:X::Y:Y",
"X:X:X:X:X:X::Y:Y"
};
const std::regex re1{ R"((((X:){1,1}(:Y){1,6})|((X:){1,2}(:Y){1,5})|((X:){1,3}(:Y){1,4})|((X:){1,4}(:Y){1,3})|((X:){1,5}(:Y){1,2})|((X:){1,6}(:Y){1,1})))" };
const std::regex re2{ R"(((X:)|(:Y)))" };
int main() {
std::smatch sm;
// Go through all test strings
for (const std::string s : test) {
// Look for a match
if (std::regex_match(s, sm, re1)) {
// Show succes message
std::cout << "Match found for --> " << s << "\n";
// Get all data (groups) into a vector
std::vector<std::string> data{ std::sregex_token_iterator(s.begin(), s.end(),re2,1), std::sregex_token_iterator() };
// Show desired groups
if (data.size() >= 6) {
std::cout << "Group 1: '" << data[0] << "' Group 6: '" << data[5] << "'\n";
}
}
else {
std::cout << "**** NO match found for --> " << s << "\n";
}
}
return 0;
}