(C++) 确定不匹配的正则表达式捕获组
(C++) Determine the unmatched regex capture groups
我想检查密码是否满足以下要求:
应该:
- 包含至少 1 个小写字母 (ASCII 97-122)
- 至少包含 1 个字母 (65-90)
- 至少包含 1 个数字
- 包含至少 1 个特殊字符(33-47、58-64、91-96、123-126)
- 长度在 8 到 20 个字符之间
它还应该告诉我哪些要求不符合。
给定以下表达式,我可以使用 std::regex
库中的 regex_match() 对其进行验证
regex re("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!-/:-@[-`{-~])(\S){8,20}$");
但是这样我只能知道匹配不匹配,因为它 returns a boolean
鉴于此,在向表达式添加一些捕获组后,我尝试像下面那样迭代 match_results
。
std::string str("AAAaaa111$$$");
std::regex rx("^((?=.*[a-z]).*)((?=.*[A-Z]).*)((?=.*[0-9]).*)((?=.*[!-/:-@[-`{-~]).*)(\S){8,20}$");
std::match_results< std::string::const_iterator > mr;
std::regex_search(str, mr, rx);
std::cout << "size: " << mr.size() << '\n'; // 6 or 0 only ?
for (int i = 0; i < mr.size(); i++) {
std::cout << "index: " << i << "\t --> \t" << mr.str(i) << endl;
}
if (regex_match(str, rx)) {
cout << "tests passed" << endl;
}
else {
cout << "tests failed" << endl;
}
它产生了以下输出:
size: 6
index: 0 --> AAAaaa111$$$
index: 1 --> AA
index: 2 --> Aa
index: 3 -->
index: 4 -->
index: 5 --> $
tests passed
Press any key to continue . . .
我想要实现的是告诉哪些组匹配失败。例如输入:SamplePassword1
只有第 4 组会匹配失败,因为它不包含特殊字符。然后可以通知用户密码不符合哪个特定 requirement/s。因此,SamplePassword1$
将在每个组中匹配并通过。
是否可以使用单个正则表达式而不是为每个要求单独使用一个正则表达式来完成此任务?
我遇到了一个有点类似的问题 here,但它在 C# .NET 中并使用命名捕获组。
var re = new Regex("((?<a>a)|(?<b>b))");
var ma = re.Match("a");
Console.WriteLine("a in a: " + ma.Groups["a"].Success); //true
Console.WriteLine("b in a: " + ma.Groups["b"].Success); //false
std::regex rx("^((?=.*[a-z]))?((?=.*[A-Z]))?((?=.*[0-9]))?((?=.*[!-/:-@[-`{-~]))?(\S){8,20}$");
并检查 mr[i].first == str.end()
。 Demo
也就是说,回想一下 the saying:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
我想检查密码是否满足以下要求:
应该:
- 包含至少 1 个小写字母 (ASCII 97-122)
- 至少包含 1 个字母 (65-90)
- 至少包含 1 个数字
- 包含至少 1 个特殊字符(33-47、58-64、91-96、123-126)
- 长度在 8 到 20 个字符之间
它还应该告诉我哪些要求不符合。
给定以下表达式,我可以使用 std::regex
库中的 regex_match() 对其进行验证
regex re("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!-/:-@[-`{-~])(\S){8,20}$");
但是这样我只能知道匹配不匹配,因为它 returns a boolean
鉴于此,在向表达式添加一些捕获组后,我尝试像下面那样迭代 match_results
。
std::string str("AAAaaa111$$$");
std::regex rx("^((?=.*[a-z]).*)((?=.*[A-Z]).*)((?=.*[0-9]).*)((?=.*[!-/:-@[-`{-~]).*)(\S){8,20}$");
std::match_results< std::string::const_iterator > mr;
std::regex_search(str, mr, rx);
std::cout << "size: " << mr.size() << '\n'; // 6 or 0 only ?
for (int i = 0; i < mr.size(); i++) {
std::cout << "index: " << i << "\t --> \t" << mr.str(i) << endl;
}
if (regex_match(str, rx)) {
cout << "tests passed" << endl;
}
else {
cout << "tests failed" << endl;
}
它产生了以下输出:
size: 6
index: 0 --> AAAaaa111$$$
index: 1 --> AA
index: 2 --> Aa
index: 3 -->
index: 4 -->
index: 5 --> $
tests passed
Press any key to continue . . .
我想要实现的是告诉哪些组匹配失败。例如输入:SamplePassword1
只有第 4 组会匹配失败,因为它不包含特殊字符。然后可以通知用户密码不符合哪个特定 requirement/s。因此,SamplePassword1$
将在每个组中匹配并通过。
是否可以使用单个正则表达式而不是为每个要求单独使用一个正则表达式来完成此任务?
我遇到了一个有点类似的问题 here,但它在 C# .NET 中并使用命名捕获组。
var re = new Regex("((?<a>a)|(?<b>b))"); var ma = re.Match("a"); Console.WriteLine("a in a: " + ma.Groups["a"].Success); //true Console.WriteLine("b in a: " + ma.Groups["b"].Success); //false
std::regex rx("^((?=.*[a-z]))?((?=.*[A-Z]))?((?=.*[0-9]))?((?=.*[!-/:-@[-`{-~]))?(\S){8,20}$");
并检查 mr[i].first == str.end()
。 Demo
也就是说,回想一下 the saying:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.