学习C++正则表达式的几个技术疑问
密码验证正则表达式疑问解答
背景
本人刚学习C++,需完成密码验证作业,觉得通过循环调用find() != string::npos的方式过于简单,于是尝试学习正则表达式。目前已实现的代码如下:
string password = "ddddDDDD333####"; if ( !regex_match(password, regex(".*[A-Z].*") ) ) { cout << "No upper case" << endl; } if ( !regex_match(password, regex(".*[a-z].*"))) { cout << "No lower case" << endl; } if ( !regex_match(password, regex(".*\\d.*"))) { cout << "No digit" << endl; }
该代码可正常运行,但希望能一次性完成所有字符规则检查,因此获取了如下正则表达式:
(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[-+_!@#$%^&*.,?]).*$
疑问解答
单独检查大写字母的方案是否有问题
你的.*[A-Z].*写法完全没问题。regex_match要求匹配整个字符串,这个模式的逻辑是:任意字符(0个或多个)+ 大写字母 + 任意字符(0个或多个),只要字符串里存在至少一个大写字母,就能匹配成功。前瞻断言的写法((?=.*[A-Z]).*)主要是为了把多个检查条件合并到单个正则里,单独做单条件检查时,你的方案逻辑清晰且正确,没必要用前瞻。正则中括号的作用及理解是否正确
这里的括号是**正向预查(零宽度前瞻断言)**的语法,格式为(?=...)。它的作用是:在当前匹配位置,检查后面是否存在符合括号内模式的内容,但不会“消耗”字符串中的字符(匹配指针不会移动),相当于给整个正则加了一个必须满足的前置条件,不是返回布尔函数。
你的理解方向是对的:每个(?=...)分别检查字符串中是否存在小写字母、大写字母、数字、指定特殊字符;因为前瞻不移动匹配指针,所以所有断言都是从字符串开头位置开始检查;最后用.*匹配整个字符串的内容,再结合$锚定结尾,确保整个密码都被验证。
- 末尾
$的作用$是正则中的结尾锚点,用来指定正则必须匹配到字符串的最后一个字符。加上它的原因是为了避免出现“密码前半部分符合规则,但后半部分存在非法字符”的情况。比如如果没有$,.*可能只匹配到密码中间某位置就停止,但加上$后,正则必须覆盖整个字符串,确保整个密码都符合规则(没有超出允许范围的字符)。
内容的提问来源于stack exchange,提问作者Kolcek2384
相关产品推荐
相关产品推荐

