正则表达式校验用户输入密码是否满足大写+小写字母+特殊字符+数字并且不少于8位的要求
|
admin
2026年4月22日 8:50
本文热度 26
|
正则表达式是个好东西,如果掌握了它,对于很多字符串问题,都可以用很少的代码来解决一些用常规编码方法会比较繁琐的验证和子串提取的问题。主要缺点就是正则表达式的那个 pattern 字符串的可读性不是很好,需要很好的学习正则表达式的语法,才能比较容易得阅读。比如说,一个经典案例,而且非常具有现实实用意义,就是校验用户输入的密码需要符合一定要求,简单起见,假设我们要求用户密码需要同时满足以下条件:我们需要用一个正则表达式,验证用户输入的任意字符串,是否符合以上要求,那么这个正则表达式应该怎么写呢?很显然,包含字母,数字这些 char class 要求,它们出现的顺序是可以是任意的,所以如果我们要穷举所有的 char class 的排列方式,比如“大写字母,小写字母,数字”, etc,然后写出来,理论上大致可行,但是这样就会让 pattern 字符串非常的长,同时也让对字符串长度的要求不太好写。那么有没有更好的办法?那就是使用正则表达式里的 look-ahead assertion,也就是 (?=...) 这个特性。 翻译到中文,我觉得可以大概说成“向前看断言”。也就是“向前看”过去,要求“前面的”部分必须要匹配括号内的正则表达式,才认为匹配。这里需要解释下一些术语,比如 look-ahead,那么哪个方向才是所谓的“前面”?当前位置,顾名思义,就是想象在 c,c++ 语言里,有一个字符指针,指向当前位置。最开始,这个指针指向被搜索匹配的字符串的开头位置,然后这个指针会在搜索过程中向字符串尾部方向移动,也是内存地址较大的方向。所以这里的“前后”就是相对于这个字符指针的移动方向来说的,想象这个字符指针是一个在一条直线上行走的人,那么这条直线就是这个被搜索的字符串,它的起点是字符串起始位置,终点是字符串的尾部。所以前方指的是更靠近字符串尾部(也就是指针移动的终点)的方向。同理,更靠近字符串开头位置的方向,叫做“后方”。look-ahead assertion 有一个非常重要的特性需要记住,那就是只校验它是否成立,但是不 consume (消费)字符。那么消费字符是什么意思呢,如果我们在执行了一些指令后,我们把前面说到那个字符指针,向字符串尾部方向移动了 n 个字符,那么我们就把移动指针这个动作,叫做消费了 n 个字符。所以,不消费字符的意思就是,在校验前方的部分以后,并不会移动这个字符指针,它依然指向原来的位置。如果有多个 look-ahead assertion 连续出现呢?那么它们之间是逻辑上 AND 的关系,也就是必须全部满足,才会假定当前位置是符合目前的匹配条件的,可以继续匹配下去。如果有一个条件不满足,则当前位置就匹配失败,会被退出,这也就是短路特性。所以对于验证密码符合条件的正则表达式,就利用了 look-ahead assertion 。^.(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])这样这个字符串中必须同时有小写,有大写,有数字,才会使得上面的三个 assertion 全部为 TRUE,才会继续匹配了。注意,因为 assertion 不消费字符这个特性,所以上面的每个条件的测试,都是从当前字符位置向“前”看去验证的,这就保证了这三个 char class 出现的顺序可以任意。然后我们再加上最后一个条件,就是长度不少于 8,可以写成:^.(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{8,}$那么这个正则表达式的 pattern 就基本上可以校验上述条件了。当然,还可以对组成密码的字符都列举出来放在一个 [] 中。
阅读原文:原文链接
该文章在 2026/4/23 16:50:04 编辑过