(C++) Определите непревзойденные группы захвата регулярных выражений
Я хочу проверить, соответствует ли пароль следующим требованиям:
Должно:
- содержать как минимум 1 строчную букву (ASCII 97-122)
- содержать не менее 1 буквы (65-90)
- содержать как минимум 1 цифру
- содержать как минимум 1 специальный символ (33-47, 58-64, 91-96, 123-126)
- иметь длину от 8 до 20 символов
Следует также сказать мне, что из этих требований не соответствует.
Учитывая следующее выражение, я могу проверить его с помощью regex_match() из std::regex
библиотека
regex re("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!-/:-@[-`{-~])(\\S){8,20}$");
Но таким образом я могу только знать, соответствует ли он или нет, так как он возвращает 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-я группа не сможет соответствовать, так как она не содержит специального символа. Затем пользователь может быть уведомлен о том, какие конкретные требования не соответствуют паролю. Соответственно, SamplePassword1$
будет иметь матч в каждой из групп и пройти.
Достижима ли эта задача с использованием одного регулярного выражения, а не отдельного выражения для каждого из требований?
Здесь я столкнулся с чем-то похожим, но он написан на 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
1 ответ
std::regex rx("^((?=.*[a-z]))?((?=.*[A-Z]))?((?=.*[0-9]))?((?=.*[!-/:-@[-`{-~]))?(\\S){8,20}$");
и проверить с mr[i].first == str.end()
, демонстрация
Тем не менее, вспомнить поговорку:
Некоторые люди, сталкиваясь с проблемой, думают: "Я знаю, я буду использовать регулярные выражения". Теперь у них две проблемы.