0

使用这个正则表达式,我想匹配带有或不带有毫秒 (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()总是 5,不管有没有 ms 字段!m[4]如果没有 ms 字段,则为空字符串。这种行为是 C++ 正则表达式中的默认行为吗?或者当我对尺寸有疑问时,我应该尝试/抓住(或其他一些安全措施)吗?我的意思是......即使大小在这里也有点误导!

4

3 回答 3

3

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

在您的代码中,您有 4 个标记的子表达式,这些子表达式是否匹配对m.

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

m[4].matched
于 2016-12-20T13:19:36.997 回答
2
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/

size 返回它分配的匹配数,这基于您的正则表达式包含的捕获组的数量。

捕获组:

括号将它们之间的正则表达式分组。它们将内部正则表达式匹配的文本捕获到一个编号组中,该组可以通过编号反向引用重复使用。它们允许您将正则表达式运算符应用于整个分组的正则表达式。

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

所以这就是为什么无论你最终用 regex_match() 填充什么,你的大小都将被分配为 5。正如其他人所指出的那样,第五个是完整的比赛。

请参阅: std::match_results::size 返回什么?

于 2016-12-20T13:19:47.947 回答
0

std::smatch(aka std::match_results<std::string::const_iterator>) 基本上是一个包含 type 元素的容器std::sub_match。第一个元素是完整 regexp 表达式的匹配结果,随后的元素包含每个子表达式的匹配项。由于您的模式有 4 个子表达式,因此您将获得 5 个结果(4 + 完全匹配)。

于 2016-12-20T13:19:13.367 回答