一看就懂正则表达式
引入
在讲正则表达式前,我们不妨先从一个场景来逐渐引入。
你可能有过这样的经历:我们去某些网站注册帐号,当你在设置密码的时候,网站会提示你密码的长度范围,以及对应的规则限制(如下图)。
根据上图,我们将密码设置规则可以描述为两个条件:
(1)长度为6-16位;
(2)密码中必须包含数字,大写字母,小写字母,特殊字符(指定字符);
现在假设我们不知道正则表达式,作为程序员的你,该如何去实现这样一个密码验证呢?
下面是我写的一个校验方法(样本): /** * 校验用户密码是否满足设置规则 * * @param password 用户输入的密码 * @return true-满足;false-不满足 */ public static boolean checkPassword(String password) { // 密码不能为空 if (password == null || password.isEmpty()) { return false; } // 校验密码长度(6-16位) int len = password.length(); if (len < 6 || len > 16) { return false; } // 定义四种组合条件 boolean hasNumber = false; boolean hasSmallLetter = false; boolean hasBigLetter = false; boolean hasSpecialChar = false; // 将密码字符串拆分为单个字符,然后对每个字符进行校验 char[] chars = password.toCharArray(); for (char c : chars) { // 是否包含数字0-9 if (c >= "0" && c <= "9") { hasNumber = true; continue; } // 是否包含小写字母a-z if (c >= "a" && c <= "z") { hasSmallLetter = true; continue; } // 是否包含大写字母A-Z if (c >= "A" && c <= "Z") { hasBigLetter = true; continue; } // 是否满足指定的特殊字符 if ("~@#S%*_-+=:.?".indexOf(c) > 0) { hasSpecialChar = true; continue; } // 如果某个字符不在上面四种情况,则不满足规则 return false; } // 如果四种组合条件均满足,则符合密码设置规则 return hasNumber && hasSmallLetter && hasBigLetter && hasSpecialChar; }
这个方法写得对不对呢?我们不防用几组密码去进行验证下:
可以看到,我们列举的8组密码,都得到了验证,说明我们的方法是OK的。
但这样一个密码设置规则校验,我们就差不多写近 30 行的代码,是不是感觉有点累赘了呢?明明规则很简单,代码量却写了这么多,有没有什么方法可以简化我们的代码呢?当然有!于是,这时就可以让我们今天的主角正则表达式出场了。
下面,则是具有相同校验功能,基于正则表达式的验证方法: /** * 通过正则表达式校验用户密码是否满足设置规则 * * @param password 用户输入的密码 * @return true-满足;false-不满足 */ public static boolean checkPasswordByRegex(String password) { return Pattern.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~@#S%*_-+=:.?])[A-Za-z0-9~@#S%*_-+=:.?]{8,20}#34;, password); }
那么它写得到底对不对呢?于是,我们可以通过上面的示例数据,继续调用该方法来进行验证:
通过结果我们可以看到,他也是符合我们预期的。于是我们发现,在不用正则表达式的时候,我们的代码量近30行,而使用了正则表达式,代码就浓缩为了1行,也就是说,使用正则表达式时可以简化我们的代码。
但同时我们也可知,正则表达式具有一定的学习成本,如果你不懂正则表达式,那么你看它可能就是一头雾水,如果出了问题,更也就无从下手去修改它了。
所以,学会正则表达式还是有必要的,至少以后你的同事写出来后,不会在脑子里出现 "这是写的啥玩意儿啊?怎么我看不懂" 的想法。 正则表达式
什么是正则表达式?通过上面的案例大家可能多少有点了解了。是的,他就是通过一行字符串,来描述一定的规则(如下图箭头所指红框处)。 命名规范
正则表达式的英文为 Regular Expression,所以我们通常采用这两个单词的首几个字母合在一起,把正则表达式相关的变量名定义为 regexp(单数) 或 regexps(复数) 。
比如:
又比如,在 Java 的 String 类中,有几个相关替换的方法,它也是支持正则表达式的,他的参数命名也是 regex 。
结构组成
正则表达式通常由一些普通字符,以及一些元字符组成。
普通字符:就是本身作为一个字符时,它不具有其他含义,像我们常用的大小写字母和数字。
元字符:就是除了本身作为一个字符外,他还可以表达其他含义(下图是部分元字符节选)。
其实,我们学习正则表达式,大部分就是基于元字符的学习。 用途场景
学习了正则表达式,我们可以有哪些用途场景呢?
(1)做字符串的规则验证(比如前面的案例引入中,我们可以通过正则表达式来验证一个密码是否符合规则)。
(2)做字符串的替换(比如将一个字符串中所有的大小写字母去掉,或者替换为指定符号)。
(3)提取字符串中所需要的字符(比如一个字符串中所有的数字提取出来,组成一个新的字符串)。 Java中的正则校验
正则表达式主要用途就是校验字符串,那么在Java中,只需要通过下面这个方法即可进行校验。 boolean result = Pattern.matches(regex, input);
其中:
regex 是我们需要写的正则表达式校验规则;
input 是我们待校验的字符串;
返回的 result 就是我们校验的结果,当为 true 的时候,表示校验通过,当为 false 的时候,则表示校验不通过。 正则元字符正则:普通字符
当我们的正则表达式为一串普通字符(不包含元字符)时,校验字符串只有和正则一致时,才会校验通过。
具体效果如下:
说明:后面例子为节省篇幅,不显得累赘,就不再贴代码,只贴校验结果。 正则:d
d 表示一个数字。
如:
aaad :表示验证的字符串后面必须以 aaa 开头,且以一个数字结尾。
aaadbbb :aaa和bbb中间有一个数字
aaadd :aaa后面跟2个数字
注意:在Java定义的正则里,由于一个表示的是字符串转义,因此在Java定义带有的元字符时,还需要多写一个,即,至于其他语言,自己可查阅相关资料进行了解。
正则:D
D 表示一个非数字,它和上面 d 的意思恰好相反。
如:
DDD :则表示一个长度为3,不包含数字的字符串。
111D222 :则表示111和222中间,必须包含一个非数字。
正则:w
w 表示一个字母(大小写均可)、数字,或下划线。
如:
12w45 :则表示12和45中间必须是一个字母,数字,或下划线。
正则:WW 与 w 相反,表示这个位置的字符既不是字母、数字,也不是下划线。
也就是:特殊符号(除下划线),或者空格等满足。
如:
12w45 :则表示12和45中间是一个非字母,非数字,或非下划线。
正则:s
s 表示匹配一个看不见的符号,即空格或制表符(Tab键)
如:
88s99 :则表示88和99中间须是一个空格或制表符。
(由于我的编辑器设置了1个制表符替换为4个空格,所以这里就不列举制表符情况了)
正则:S
S 与 s 相反,表示一个可以看得见的符号。
如:
88S99 :则表示88和99中间须有一个看得见的符号。
正则:.
. (小数点) 则表示" "和"r"之外的任何单个字符。
如:
.... :则表示任意四个字符
正则:|
| (竖线) 则表示或的关系,表示检测的字符串须满足其中一个时,才符合条件。
如:
aa|bb|cc :则表示输入的字符串须是aa,或bb,或cc其中的一个。
注意,如果我们或者关系的前后还有其它字符时,需要用()将他们包裹起来。
如:
xx(aa|bb|cc)yy :则表示输入的字符串须是xx开头,yy结尾,且中间是aa,或bb,或cc其中的一个。
正则:[abc]
[ ] 表示匹配其中任意一个字符。
如:
a[bcd]e :则表示a和e的中间须是b,或c,或d其中的一个
注意:用 | 表示其中之一,他可以是字符,也可以是字符串。而只用中括号时,则只表示其中一个字符。 正则:[^abc]
[^ ] 表示不与中括号里的任意字符匹配。
如:
a[^bcd]e :则表示a和e的中间除b,c,d这三个字符外,其他的字符都满足。
正则:[a-z]
[值1-值2] 则表示值1到值2中间的所有字符都满足(包括值1和值2)。常用该正则来表示大小写字母范围,数字范围。
如:
a[b-d]e: 等同于 a[bcd]e ,因为 b-d 其实就是b,c,d三个数。
a[0-9]e: 则表示a和e中间是一个数字,等同于 ade (前面说过d表示一个数字)
正则:[^a-z]
[^值1-值2] 则表示除值1和值2之外的所有字符,都可以满足。
如:
a[^1-3]e :则表示a和e中间的字符,只要不是1,2,3,则都满足。
正则: um
这里的num指number,也就是数字,当后面跟数字,表示匹配第几个括号中的结果。
比如:现在有 abcd 字符串,当我们用小括号把 c 包裹起来后,然后在字符串后面写上 1,即 ab(c)d1,则这里的 1 就指 c,因为 1 表示第1个小括号中的结果。
ab(c)d1 :等同于 abcdc 。
如果我们继续把 ab(c)d1 中的 d 包括起来,并在后面写上 2,即 ab(c)(d)12, 那么这里的 2 就表示 d 这个字符,因为第2个小括号的结果是 d,所以整个表达式就等同于 abcdcd 。
ab(c)(d)12 :等同于 abcdcd,也等同于 ab(cd)1 。
正则:?
? 表示匹配前面的子表达式零次或一次。
如:
abc?de : 表示可匹配的字符串为 abde (匹配0次c) 或 abcde (匹配1次c)。
正则:+
匹配前面的子表达式一次或多次 (次数 >= 1,即至少1次)
如:
abc+de: ab 和 de 之前至少有一个 c 。
正则:{n}
这里的 n 是一个非负整数。匹配确定的前面的子表达式 n 次。
如:
abc{3}de :表示 ab 和 de 之间有3个c。
ab(xx|yy){3}de :表示 ab 和 de 之间有 xx 或 yy 的个数, 一起合计为3个。
正则:{n,m}
m和n均为非负整数,其中 n<=m。最少匹配 n 次且最多匹配 m 次。
如:
abc{2,3}de :表示 ab 和 de 之间有 2 到 3 个 c。
正则:*
表示匹配前面的子表达式任意次。
如:
abc*de :表示 ab 和 de 之间有任意个数(包括0)c 。
向云迁徙中台实践云徙科技携手企业探索数字化转型云徙就是向云迁徙,帮助企业向通过云计算和大数据的方式向云端迁徙,云徙科技创始人兼CEO包志刚说明了公司名字的来源。9月25日,2020云徙数字创新年会在杭州召开。大会围绕企业数字化
中台战略到中台实践,云徙科技如何拆解中台建设方法论?倘若给科技圈这两年的热词排个序,中台一定榜上有名。中台诞生不过数年,但是其受到的关注度丝毫不弱于一门基础编程语言,归根究底,中台和其追随者们踏入了时代洪流。在日前权威部门正式印发的
云徙科技CEO包志刚数字化转型的道法术2020每一件事都是危与机并存。数字经济时代的到来,让一批企业衰落,也同时催生了一批新企业的诞生。但企业对于数字化的目标实现过程运用工具,到底是什么样的?在2020年云徙数字创新年
数字中台,数字化的全速重构与全面转型不要浪费一场危机的机会。对于参与企业数字化转型的所有实践者们而言,今年突出其来的新冠疫情,是危机,更是机会。他们深刻认识到,消费环境复杂多变,企业面临生态模式的重塑,跟得上用户需求
数字中台全速重构企业业务与IT2020云徙数创年会召开9月25日,2020云徙数字创新年会在杭州召开。作为今年的中台实践第一峰会,峰会当天有超过400位龙头企业信息化相关人员出席线下活动,线上更有百万人次通过云徙科技官网各大直播平台等
中台实践正式发布!近百家龙头企业的中台建设启示录到底如何建中台?。这恐怕已经成为很多数字化转型的企业高管正在面临的困局。很多人都想知道,行业的头部企业是如何借中台达成数字化转型的?近日,在2020云徙数字创新年会举行期间,由云徙
全新解读云徙数舰数字中台日前,权威部门正式印发关于加快推进国有企业数字化转型工作的通知,明确国有企业数字化转型的基础方向重点和举措,开启了国有企业数字化转型的新篇章。记者注意到,通知中明确强调了数字化转型
有了这款杯子,不用去咖啡店,在家也能做冷萃?炎热的夏日即将到来,不少小伙伴早早就准备好度夏的装备了。除了像空调冰激凌冰可乐这些常见的东西之外,小编认为今年的度夏装备应该再加上我手上的这台东菱乐萃杯!在烈日炎炎的季节里,烈日炎
智能运动手表也有更多选择?咕咚X3RE智能运动手表会给你答案智能运动手表想必在座的各位应该都有了解吧,如今随着物联网的发展越来越多的手机厂商都推出了自家的智能运动手表。不过这些手机厂商所推出的手表在不同系统之间的兼容性方面表现并不是特别优秀
云徙汽车邓通汽车数字化的下一个10年对于汽车行业来说,2020年是非常特殊的一年,对汽车行业的打击非常大,并且从2018年开始,汽车行业已经整体从增量市场进入到存量市场。这时,我们发现很多主机厂在品牌用户运营方面出现
三生孙鹏博大健康产业的5年数字化实践点击查看大会精彩回放近两年,直销行业在内忧外患之下,行业整体遭受到了不小的冲击。不过,数字技术催生了新的商业模式,也让直销在国内出现几十年的行业焕发了新的活力。三生作为直销行业的领