C++ 正则表达式:非贪婪匹配
C++ Regex: non-greedy match
我目前正在尝试制作一个匹配 URL 参数并提取它们的正则表达式。
比如我得到如下参数字符串?param1=someValue¶m2=someOtherValue
,std::regex_match
应该提取如下内容:
param1
some_content
param2
some_other_content
在尝试了不同的正则表达式模式之后,我终于构建了一个与我想要的相对应的模式:std::regex("(?:[\?&]([^=&]+)=([^=&]+))*")
。
如果我采用前面的示例,std::regex_match
会按预期匹配。但是,它不会提取预期值,只保留最后捕获的值。
例如下面的代码:
std::regex paramsRegex("(?:[\?&]([^=&]+)=([^=&]+))*");
std::string arg = "?param1=someValue¶m2=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
returns false 并且没有捕获任何内容)。
我尝试了不同的 std::regex_constants
选项(使用 std::regex_constants::grep
、std::regex_constants::egrep
、...的不同正则表达式语法)但结果是一样的。
有人知道如何在 C++ 中进行非贪婪正则表达式捕获吗?
作为Casimir et Hippolyte explained in his ,我只需要:
- 删除量词
- 使用
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
,我可以检索参数值。
尝试使用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();
}
我目前正在尝试制作一个匹配 URL 参数并提取它们的正则表达式。
比如我得到如下参数字符串?param1=someValue¶m2=someOtherValue
,std::regex_match
应该提取如下内容:
param1
some_content
param2
some_other_content
在尝试了不同的正则表达式模式之后,我终于构建了一个与我想要的相对应的模式:std::regex("(?:[\?&]([^=&]+)=([^=&]+))*")
。
如果我采用前面的示例,std::regex_match
会按预期匹配。但是,它不会提取预期值,只保留最后捕获的值。
例如下面的代码:
std::regex paramsRegex("(?:[\?&]([^=&]+)=([^=&]+))*");
std::string arg = "?param1=someValue¶m2=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
returns false 并且没有捕获任何内容)。
我尝试了不同的 std::regex_constants
选项(使用 std::regex_constants::grep
、std::regex_constants::egrep
、...的不同正则表达式语法)但结果是一样的。
有人知道如何在 C++ 中进行非贪婪正则表达式捕获吗?
作为Casimir et Hippolyte explained in his
- 删除量词
- 使用
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
,我可以检索参数值。
尝试使用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();
}