C++11:使用正则表达式进行两种可能的匹配次数的安全实践

C++11: Safe practice with regex of two possible number of matches

对于 this regex,我想匹配带或不带毫秒 (ms) 字段的时间。为了完整起见,我在这里编写正则表达式(我删除了 regex101 中的锚点以启用多行):

^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:|(?:\.)([0-9]{1,6}))$

我有点不明白这个的 C++ 行为。现在您在 regex101 中看到,捕获组的数量取决于字符串。如果没有 ms,则为 3+1(因为 C++ 使用 match[0] 作为匹配模式),如果有 ms,则为 4+1。但是在这个例子中:

std::regex timeRegex = std::regex(R"(^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:|(?:\.)([0-9]{1,6}))$)");
std::smatch m;
std::string strT = std::string("12:00:09");
bool timeMatch = std::regex_match(strT, m, timeRegex);
std::cout<<m.size()<<std::endl;
if(timeMatch)
{
    std::cout<<m[0]<<std::endl;
    std::cout<<m[1]<<std::endl;
    std::cout<<m[2]<<std::endl;
    std::cout<<m[3]<<std::endl;
    std::cout<<m[4]<<std::endl;
}

我们看到m.size()不管有没有ms字段,都是5!如果没有 ms 字段,m[4] 是一个空字符串。这种行为是 C++ 正则表达式中的默认行为吗?还是在不确定尺寸时我应该 try/catch (或其他一些安全措施)?我的意思是...即使尺寸在这里也有点误导!

std::smatch (a.k.a. std::match_results<std::string::const_iterator>) 基本上是一个容器,其中包含 std::sub_match 类型的元素。第一个元素是完整正则表达式的匹配结果,随后的元素包含每个子表达式的匹配项。因为如果你的模式有 4 个子表达式,你会得到 5 个结果(4 + 完全匹配)。

m.size() 将始终是表达式中标记的子表达式的数量加 1(对于整个表达式)。

在您的代码中您有 4 个标记的子表达式,它们是否匹配对 m 的大小没有影响。

如果你想知道现在是否有毫秒,你可以查看:

m[4].matched
m.size();// Returns the number of match results. 
         // a string is allocated for each 'Capture Group' 
         // and filled with the match substring. 

因为 smatch 是 match_results

(见) http://www.cplusplus.com/reference/regex/match_results/

大小 returns 它分配的匹配项数,它基于您的正则表达式包含的捕获组数。

捕获组:

Parentheses group the regex between them. They capture the text matched by the regex inside them into a numbered group that can be reused with a numbered backreference. They allow you to apply regex operators to the entire grouped regex.

http://www.regular-expressions.info/refcapture.html

所以这就是为什么无论您最终用 regex_match() 填充什么,您的大小都会被分配为 5。正如其他人所说,第五个是完整匹配。

见: