C ++ Regex: не жадное совпадение

В настоящее время я пытаюсь сделать регулярное выражение, которое соответствует параметрам URL и извлекает их.

Например, если я получил следующую строку параметров ?param1=someValue&param2=someOtherValue, std::regex_match следует извлечь следующее содержимое:

  • param1
  • some_content
  • param2
  • some_other_content

Попробовав различные шаблоны регулярных выражений, я наконец-то создал шаблон, соответствующий тому, что хочу: std::regex("(?:[\\?&]([^=&]+)=([^=&]+))*"),

Если я возьму предыдущий пример, std::regex_match соответствует, как ожидалось. Однако он не извлекает ожидаемые значения, сохраняя только последние зафиксированные значения.

Например, следующий код:

std::regex paramsRegex("(?:[\\?&]([^=&]+)=([^=&]+))*");
std::string arg = "?param1=someValue&param2=someOtherValue";
std::smatch sm;

std::regex_match(arg, sm, paramsRegex);
for (const auto &match : sm)
std::cout << match << std::endl;

даст следующий вывод:

param2
someOtherValue

Как видите, param1 и его значение пропускаются и не фиксируются.

После поиска в Google, я обнаружил, что это связано с жадным захватом, и я изменил свое регулярное выражение в "(?:[\\?&]([^=&]+)=([^=&]+))\\*?" для того, чтобы включить нежадный захват.

Это регулярное выражение хорошо работает, когда я пытаюсь Rubular но это не совпадает, когда я использую его в C ++ (std::regex_match возвращает false и ничего не фиксируется).

Я пробовал разные std::regex_constants варианты (различные грамматики регулярных выражений с помощью std::regex_constants::grep, std::regex_constants::egrep, …) но результат тот же.

Кто-нибудь знает, как сделать не жадный захват регулярных выражений в C ++?

1

Решение

Как Казимир и Ипполит объяснил в своем комментарий, Мне просто нужно:

  • удалить квантификатор
  • использование std::regex_iterator

Это дает мне следующий код:

std::regex paramsRegex("[\\?&]([^=]+)=([^&]+)");
std::string url_params = "?key1=val1&key2=val2&key3=val3&key4=val4";
std::smatch sm;

auto params_it = std::sregex_iterator(url_params.cbegin(), url_params.cend(), paramsRegex);
auto params_end = std::sregex_iterator();

while (params_it != params_end) {
auto param = params_it->str();

std::regex_match(param, sm, paramsRegex);
for (const auto &s : sm)
std::cout << s << std::endl;

++params_it;
}

И вот вывод:

?key1=val1
key1
val1
&key2=val2
key2
val2
&key3=val3
key3
val3
&key4=val4
key4
val4

Оригинальное регулярное выражение (?:[\\?&]([^=&]+)=([^=&]+))* был просто изменен на [\\?&]([^=]+)=([^&]+),

Затем, используя std::sregex_iteratorЯ получаю итератор для каждой соответствующей группы (?key1=val1, &key2=val2…)

Наконец, позвонив std::regex_match по каждой подстроке я могу получить значения параметров.

3

Другие решения

Попробуйте использовать match_results :: префикс / суффикс:

string match_expression("your expression");
smatch result;
regex fnd(match_expression, regex_constants::icase);
while (regex_search(in_str, result, fnd, std::regex_constants::match_any))
{
for (size_t i = 1; i < result.size(); i++)
{
std::cout << result[i].str();
}
in_str = result.suffix();
}
0

По вопросам рекламы [email protected]