2015-05-02 85 views
1

我目前正在嘗試製作一個匹配URL參數並提取它們的正則表達式。C++正則表達式:非貪婪匹配

例如,如果我得到了下面的參數字符串?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 

正如你所看到的,參數1和它的價值被跳過,而不是捕捉。

在谷歌搜索後,我發現這是由於貪婪的捕獲,我已經修改了我的正則表達式到"(?:[\\?&]([^=&]+)=([^=&]+))\\*?"以便啓用非貪婪捕獲。

這個正則表達式運行良好,當我在rubular上嘗試時,但它在C++中使用時不匹配(std::regex_match返回false並且沒有捕獲任何內容)。

我試過不同的std::regex_constants選項(使用std::regex_constants::grep,std::regex_constants::egrep,...的不同的正則表達式語法),但結果是一樣的。

有人知道如何在C++中做非貪婪的正則表達式捕獲?

+4

捕獲組的每個repeatition覆蓋以前。您需要刪除量詞'[?&]([^ =] +)=([^&] +)'並使用正則表達式迭代器獲取不同的匹配項:http://en.cppreference.com/w/cpp/regex/regex_iterator。這不是一個貪婪/不貪婪的問題。 –

+0

謝謝你的解釋:我用regex_iterators嘗試過,它效果很好! –

回答

3

由於Casimir et Hippolyte在他comment解釋,我只需要:

  • 刪除量詞
  • 使用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,我可以檢索參數值。

0

嘗試使用一個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(); 
}