首页 文章

C正则表达式:非贪婪的比赛

提问于
浏览
1

我正在尝试制作一个匹配URL参数的正则表达式并提取它们 .

例如,如果我得到以下参数字符串 ?param1=someValue&param2=someOtherValuestd::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及其值被跳过而不被捕获 .

在谷歌搜索后,我发现这是由于贪婪的捕获,我已将我的正则表达式修改为 "(?:[\\?&]([^=&]+)=([^=&]+))\\*?" ,以便启用非贪婪的捕获 .

当我在rubular上尝试时,这个正则表达式运行良好但是当我在C中使用它时它不匹配( std::regex_match 返回false并且没有捕获任何内容) .

我尝试了不同的 std::regex_constants 选项(使用 std::regex_constants::grepstd::regex_constants::egrep ,...不同的正则表达式语法)但结果是一样的 .

有人知道如何在C中进行非贪婪的正则表达式捕获吗?

2 回答

  • 3

    正如Casimir et Hippolyte在他的_1560347中解释的那样,我只需要:

    • 删除量词

    • 使用 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
    

    orignal正则表达式 (?:[\\?&]([^=&]+)=([^=&]+))* 刚刚变为 [\\?&]([^=]+)=([^&]+) .

    然后,通过使用 std::sregex_iterator ,我在每个匹配的组上获得一个迭代器( ?key1=val1&key2=val2 ,...) .

    最后,通过在每个子字符串上调用 std::regex_match ,我可以检索参数值 .

  • 0

    尝试使用match_results :: prefix / suffix:

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

相关问题