案例引入

在我们去某些网站注册帐号,当你在设置密码的时候,网站会提示你密码的长度范围,以及对应的规则限制(如下图)。

图片图片

根据上图,我们将密码设置规则可以描述为两个条件:

  • 长度为6-16位;
  • 密码中必须包含数字,大写字母,小写字母,特殊字符(指定字符);

基于此案例,我们就可以用正则表达式的方法进行验证:

1
2
3
4
5
6
7
8
9
/**
* 通过正则表达式校验用户密码是否满足设置规则
*
* @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}$", password);
}

我们可以通过上面的示例数据,调用该方法来进行验证:

图片

通过结果我们可以看到,我们只用了一两行代码就能对输入的密码进行验证,如果单纯使用代码的话可能要几十行代码进行判断。

正则表达式

什么是正则表达式?通过上面的案例大家可能多少有点了解了。是的,他就是通过一行字符串,来描述一定的规则(如下图箭头所指红框处)。

1、结构组成

正则表达式通常由一些普通字符,以及一些元字符组成。

普通字符:就是本身作为一个字符时,它不具有其他含义,像我们常用的大小写字母和数字。

元字符:就是除了本身作为一个字符外,他还可以表达其他含义(下图是部分元字符节选)。

图片

其实,我们学习正则表达式,大部分就是基于元字符的学习。

2、用途场景

学习了正则表达式,我们可以有哪些用途场景呢?

1)做字符串的规则验证(比如前面的案例引入中,我们可以通过正则表达式来验证一个密码是否符合规则)。

2)做字符串的替换(比如将一个字符串中所有的大小写字母去掉,或者替换为指定符号)。

3)提取字符串中所需要的字符(比如一个字符串中所有的数字提取出来,组成一个新的字符串)。

3、Java中的正则校验

正则表达式主要用途就是校验字符串,那么在Java中,只需要通过下面这个方法即可进行校验。

1
boolean result = Pattern.matches(regex, input);

其中:

  • regex 是我们需要写的正则表达式校验规则;
  • input 是我们待校验的字符串;

返回的 result 就是我们校验的结果,当为 true 的时候,表示校验通过,当为 false 的时候,则表示校验不通过。

4、正则元字符

普通字符

当我们的正则表达式为一串普通字符(不包含元字符)时,校验字符串只有和正则一致时,才会校验通过。

具体效果如下:

图片

说明:后面例子为节省篇幅,不显得累赘,就不再贴代码,只贴校验结果。


\d :表示一个数字。

  • aaa\d: 表示验证的字符串后面必须以 aaa 开头,且以一个数字结尾。

  • aaa\dbbb:aaa和bbb中间有一个数字

  • aaa\d\d:aaa后面跟2个数字

注意:在Java定义的正则里,由于一个\表示的是字符串转义,因此在Java定义带有\的元字符时,还需要多写一个\,即\

图片


\D 表示一个非数字,它和上面 \d 的意思恰好相反。

  • \D\D\D: 则表示一个长度为3,不包含数字的字符串。

  • 111\D222:则表示111和222中间,必须包含一个非数字。


\w 表示一个字母(大小写均可)、数字,或下划线。

  • 12\w45:则表示12和45中间必须是一个字母,数字,或下划线。

\W 与 \w 相反,表示这个位置的字符既不是字母、数字,也不是下划线。

也就是:特殊符号(除下划线),或者空格等满足。

  • 12\w45:则表示12和45中间是一个非字母,非数字,或非下划线。

\s 表示匹配一个看不见的符号,即空格或制表符(Tab键)

  • 88\s99:则表示88和99中间须是一个空格或制表符。

由于我的编辑器设置了1个制表符替换为4个空格,所以这里就不列举制表符情况了


\S 与 \s 相反,表示一个可以看得见的符号。

  • 88\S99:则表示88和99中间须有一个看得见的符号。

. (小数点) 则表示“\n”和”\r”之外的任何单个字符。

  • …. :则表示任意四个字符

| (竖线) 则表示或的关系,表示检测的字符串须满足其中一个时,才符合条件。

如:

  • aa|bb|cc:则表示输入的字符串须是aa,或bb,或cc其中的一个。

注意,如果我们或者关系的前后还有其它字符时,需要用()将他们包裹起来。

  • xx(aa|bb|cc)yy:则表示输入的字符串须是xx开头,yy结尾,且中间是aa,或bb,或cc其中的一个。

[ ] 表示匹配其中任意一个字符。

  • a[bcd]e:则表示a和e的中间须是b,或c,或d其中的一个

注意:用 | 表示其中之一,他可以是字符,也可以是字符串。而只用中括号时,则只表示其中一个字符。


表示不与中括号里的任意字符匹配。

  • a[^bcd]e:则表示a和e的中间除b,c,d这三个字符外,其他的字符都满足。

[值1-值2] 则表示值1到值2中间的所有字符都满足(包括值1和值2)。常用该正则来表示大小写字母范围,数字范围。

  • a[b-d]e:等同于 a[bcd]e,因为 b-d 其实就是b,c,d三个数。

  • a[0-9]e:则表示a和e中间是一个数字,等同于 a\de(前面说过\d表示一个数字)


值1-值2 则表示除值1和值2之外的所有字符,都可以满足。

  • a[^1-3]e:则表示a和e中间的字符,只要不是1,2,3,则都满足。

\num 这里的num指number,也就是数字,当\后面跟数字,表示匹配第几个括号中的结果。

比如:现在有 abcd 字符串,当我们用小括号把 c 包裹起来后,然后在字符串后面写上 \1,即 ab(c)d\1,则这里的 \1 就指 c,因为 \1 表示第1个小括号中的结果。

  • ab(c)d\1:等同于 abcdc 。

图片

如果我们继续把 ab(c)d\1 中的 d 包括起来,并在后面写上 \2,即 ab(c)(d)\1\2, 那么这里的 \2 就表示 d 这个字符,因为第2个小括号的结果是 d,所以整个表达式就等同于 abcdcd 。

  • ab(c)(d)\1\2:等同于 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个。

图片


{m,n} m和n均为非负整数,其中 n<=m。最少匹配 n 次且最多匹配 m 次。

  • abc{2,3}de:表示 ab 和 de 之间有 2 到 3 个 c。

图片


* 表示匹配前面的子表达式任意次。

如:

  • abc*de:表示 ab 和 de 之间有任意个数(包括0)c 。

图片