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.
所以这就是为什么无论您最终用 regex_match() 填充什么,您的大小都会被分配为 5。正如其他人所说,第五个是完整匹配。
见:
对于 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.
所以这就是为什么无论您最终用 regex_match() 填充什么,您的大小都会被分配为 5。正如其他人所说,第五个是完整匹配。
见: