引入 在讲正则表达式前,我们不妨先从一个场景来逐渐引入。 你可能有过这样的经历:我们去某些网站注册帐号,当你在设置密码的时候,网站会提示你密码的长度范围,以及对应的规则限制(如下图)。 根据上图,我们将密码设置规则可以描述为两个条件: (1)长度为616位; (2)密码中必须包含数字,大写字母,小写字母,特殊字符(指定字符); 现在假设我们不知道正则表达式,作为程序员的你,该如何去实现这样一个密码验证呢? 下面是我写的一个校验方法(样本):校验用户密码是否满足设置规则parampassword用户输入的密码returntrue满足;false不满足publicstaticbooleancheckPassword(Stringpassword){密码不能为空if(passwordnullpassword。isEmpty()){returnfalse;}校验密码长度(616位)intlenpassword。length();if(len6len16){returnfalse;}定义四种组合条件booleanhasNumberfalse;booleanhasSmallLetterfalse;booleanhasBigLetterfalse;booleanhasSpecialCharfalse;将密码字符串拆分为单个字符,然后对每个字符进行校验char〔〕charspassword。toCharArray();for(charc:chars){是否包含数字09if(c0c9){hasNumbertrue;continue;}是否包含小写字母azif(cacz){hasSmallLettertrue;continue;}是否包含大写字母AZif(cAcZ){hasBigLettertrue;continue;}是否满足指定的特殊字符if(S:。?。indexOf(c)0){hasSpecialChartrue;continue;}如果某个字符不在上面四种情况,则不满足规则returnfalse;}如果四种组合条件均满足,则符合密码设置规则returnhasNumberhasSmallLetterhasBigLetterhasSpecialChar;} 这个方法写得对不对呢?我们不防用几组密码去进行验证下: 可以看到,我们列举的8组密码,都得到了验证,说明我们的方法是OK的。 但这样一个密码设置规则校验,我们就差不多写近30行的代码,是不是感觉有点累赘了呢?明明规则很简单,代码量却写了这么多,有没有什么方法可以简化我们的代码呢?当然有!于是,这时就可以让我们今天的主角正则表达式出场了。 下面,则是具有相同校验功能,基于正则表达式的验证方法:通过正则表达式校验用户密码是否满足设置规则parampassword用户输入的密码returntrue满足;false不满足publicstaticbooleancheckPasswordByRegex(Stringpassword){returnPattern。matches((?。〔09〕)(?。〔az〕)(?。〔AZ〕)(?。〔S:。?〕)〔AZaz09S:。?〕{8,20}34;,password);} 那么它写得到底对不对呢?于是,我们可以通过上面的示例数据,继续调用该方法来进行验证: 通过结果我们可以看到,他也是符合我们预期的。于是我们发现,在不用正则表达式的时候,我们的代码量近30行,而使用了正则表达式,代码就浓缩为了1行,也就是说,使用正则表达式时可以简化我们的代码。 但同时我们也可知,正则表达式具有一定的学习成本,如果你不懂正则表达式,那么你看它可能就是一头雾水,如果出了问题,更也就无从下手去修改它了。 所以,学会正则表达式还是有必要的,至少以后你的同事写出来后,不会在脑子里出现这是写的啥玩意儿啊?怎么我看不懂的想法。正则表达式 什么是正则表达式?通过上面的案例大家可能多少有点了解了。是的,他就是通过一行字符串,来描述一定的规则(如下图箭头所指红框处)。命名规范 正则表达式的英文为RegularExpression,所以我们通常采用这两个单词的首几个字母合在一起,把正则表达式相关的变量名定义为regexp(单数)或regexps(复数)。 比如: 又比如,在Java的String类中,有几个相关替换的方法,它也是支持正则表达式的,他的参数命名也是regex。 结构组成 正则表达式通常由一些普通字符,以及一些元字符组成。 普通字符:就是本身作为一个字符时,它不具有其他含义,像我们常用的大小写字母和数字。 元字符:就是除了本身作为一个字符外,他还可以表达其他含义(下图是部分元字符节选)。 其实,我们学习正则表达式,大部分就是基于元字符的学习。用途场景 学习了正则表达式,我们可以有哪些用途场景呢? (1)做字符串的规则验证(比如前面的案例引入中,我们可以通过正则表达式来验证一个密码是否符合规则)。 (2)做字符串的替换(比如将一个字符串中所有的大小写字母去掉,或者替换为指定符号)。 (3)提取字符串中所需要的字符(比如一个字符串中所有的数字提取出来,组成一个新的字符串)。Java中的正则校验 正则表达式主要用途就是校验字符串,那么在Java中,只需要通过下面这个方法即可进行校验。booleanresultPattern。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之外的任何单个字符。 如: 。。。。:则表示任意四个字符 正则: (竖线)则表示或的关系,表示检测的字符串须满足其中一个时,才符合条件。 如: aabbcc:则表示输入的字符串须是aa,或bb,或cc其中的一个。 注意,如果我们或者关系的前后还有其它字符时,需要用()将他们包裹起来。 如: xx(aabbcc)yy:则表示输入的字符串须是xx开头,yy结尾,且中间是aa,或bb,或cc其中的一个。 正则:〔abc〕 〔〕表示匹配其中任意一个字符。 如: a〔bcd〕e:则表示a和e的中间须是b,或c,或d其中的一个 注意:用表示其中之一,他可以是字符,也可以是字符串。而只用中括号时,则只表示其中一个字符。正则:〔abc〕 〔〕表示不与中括号里的任意字符匹配。 如: a〔bcd〕e:则表示a和e的中间除b,c,d这三个字符外,其他的字符都满足。 正则:〔az〕 〔值1值2〕则表示值1到值2中间的所有字符都满足(包括值1和值2)。常用该正则来表示大小写字母范围,数字范围。 如: a〔bd〕e:等同于a〔bcd〕e,因为bd其实就是b,c,d三个数。 a〔09〕e:则表示a和e中间是一个数字,等同于ade(前面说过d表示一个数字) 正则:〔az〕 〔值1值2〕则表示除值1和值2之外的所有字符,都可以满足。 如: a〔13〕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次) 如: abcde:ab和de之前至少有一个c。 正则:{n} 这里的n是一个非负整数。匹配确定的前面的子表达式n次。 如: abc{3}de:表示ab和de之间有3个c。 ab(xxyy){3}de:表示ab和de之间有xx或yy的个数,一起合计为3个。 正则:{n,m} m和n均为非负整数,其中nm。最少匹配n次且最多匹配m次。 如: abc{2,3}de:表示ab和de之间有2到3个c。 正则: 表示匹配前面的子表达式任意次。 如: abcde:表示ab和de之间有任意个数(包括0)c。