【Java杂记】正则表达式:基本语法及Java中使用(Pattern&Matcher)

472 阅读3分钟

1.正则表达式

正则表达式用于字符串格式匹配,构造正则的实质是造句。下面我们就来看看正则的表达式的基本语法...

1.1 基本语法

1.字符匹配

字符语法语法解释语法例子
.匹配任意字符‘....’匹配A$ 5,不匹配换行;
\d匹配数字(0~9)‘\d’匹配8,不匹配12;
\D匹配非数字‘\D’匹配c,不匹配3;
\w匹配任意单字符‘\w\w’ 匹配A3,不匹配@3;
\W匹配非单字符‘\W’匹配@,不匹配c;
\s匹配空白字符‘\d\s\d’匹配3 d,不匹配abc;
\S匹配非空字符‘\S\S\S’匹配A#4,不匹配3 d;
[…]匹配括号中任意字符[b-d]匹配b、c、d, 不匹配e;
[^…]匹配非括号字符[^b-z]匹配a,不匹配b-z的字符;

2.重复匹配

重复匹配是对其前一个字符的重复次数,若要多个字符重复可以加( )

字符功能
*匹配前一个字符出现0次或者无限次,即可有可无
+匹配前一个字符出现1次或者无限次,即至少1次
?匹配前一个字符出现1次或者0次,即至多1次
{m}匹配前一个字符出现m次
{m,}匹配前一个字符至少出现m次
{m,n}匹配前一个字符出现从m到n次

3.边界符

  • ():表示分组
    • 将( )内容作为一个整体,配合数量匹配;如(abc)+,匹配至少一个abc
    • 提取指定匹配内容;如在匹配的日期字符串中,提取小时
  • ^:开始位置
  • $:结束位置

4.转义字符

  • 对于正则中已经有的字符,使用其字面义时要转义

    • \.
    • \*
    • \[ \]
  • 另外还有代表指定意义的转义字符

    • \n:换行
    • \t:制表符
    • \f:换页

1.2 正则示例

  1. /^[0-9]{1,20}$/

    表示字符串全部由数字组成,即是匹配当前字符串是否是由全数字组成

    • [0-9] 表示字符的范围是0到9
    • {1,20}表示字符串长度至少为1,最多为20,字符串出现次数的范围
  2. /^[a-zA-Z]{1}([a-zA-Z0-9._]){5,15}$/

    可以用来验证登录名,首字母为字母,长度为至少6最多16

    • ^[a-zA-Z]{1} 表示最开始的第一个首字母为字母
    • ([a-zA-Z0-9._]){5,15} 这是首字母后面的即是从第二个字母开始,要求至少再有5个最多15个,由字母数字以及指定特殊字符组成的字符串
  3. /^[1][3|4|5|8][0-9]\d{8}$/

    可以用来验证手机号码,首字母为1,长度11,首尾都是数字

    • ^[1] 第一个数字为1
    • [3|4|5|8] 第二个数字为 3或者4或者5或者8
    • [0-9] 第三个数字为0-9任一个
    • \d{8} 匹配一个数字范围是0-9,匹配8次,所以至少要有8个数字。加起来就是11个
  4. /^(\w){6,20}$/

    验证密码

    • \w 匹配任何非单词字符 等价于“[^A-Za-z0-9_]
    • (\w){6,20} 匹配任何非单词字符,最少6个最多20个

2.Java:Pattern -> Matcher

上面我们认识了正则表达式,那在Java中如何通过正则进行字符串格式匹配呢?答:通过 Pattern 和 Matcher 两个类。

使用流程

  1. 将String类型的正则表达式传入Pattern.compile(),生成Pattern对象,表示编译后的表达式
// compile是编译的意思,入参正则表达式
Pattern pattern = Pattern.compile("\d\d\d");
  1. 通过 Pattern.matcher(目标字符串),返回Matcher,然后再通过Matcher进行一系列匹配操作

    注:一个正则可以匹配多个字符串,相应的一个Pattern可以有多个Matcher实例

// match是匹配的意思,入参是要与正则匹配的目标字符串
Matcher matcher = pattern.matcher("a12345bb");
  1. 然后就可以调用 Matcher 的 matches,find 等方法对该字符串进行格式匹配。具体如下...

2.1 matches():整体匹配

整体匹配:尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值.

Pattern pattern = Pattern.compile("\\?{2}");
Matcher matcher = pattern.matcher("??");
boolean matches = matcher.matches();// true

matcher = pattern.matcher("?");
matches = matcher.matches(); // false

2.2 find():局部匹配

局部匹配:对字符串进行匹配,匹配到的字符串可以在任何位置

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("22bb23");
m.find(); // 返回true

Matcher m2 = p.matcher("aa2223");
m2.find(); // 返回true

Matcher m3 = p.matcher("aa2223bb");
m3.find(); // 返回true

Matcher m4 = p.matcher("aabb");
m4.find(); // 返回false

2.3 lookingAt() :头部匹配

头部匹配:对前面的字符串进行匹配,只有匹配到的字符串在最前面才会返回true

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("22bb23");
boolean match = m.lookingAt();// true

m = p.matcher("bb2233");
match= m.lookingAt(); // false

2.4 group() & start() & end()

  • String group() 返回匹配到的子字符串,若要获取局部内容,可通过分组实现
  • int start() 返回当前匹配到的字符串在原目标字符串中的位置
  • int end() 返回当前匹配的字符串的最后一个字符在原目标字符串中的索引位置.
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("aa22bb23");

int start = m.start();//2
String group = m.group();//22
int end = m.end();//4
Pattern p = Pattern.compile("^\\[(.*)\\](\\s\\-\\s(.*))?");
Matcher m = pattern.matcher(msg);
if(m.matches()){
    // 根据索引获取局部分组内容
    String header = m.group(1);
    String content = m.group(3);
}

最后,还要明白个问题,String 中也有个 matches 方法,跟上面的 Pattern 和 Matcher 有什么关系呢?这还要从源码中找答案:

// String中的matches方法
public boolean matches(String regex) {
    // 实际也是调用Matcher.matches方法进行全匹配
    return Pattern.matches(regex, this);
}

所以,当要与正则进行整体匹配时,可以直接调用String的matches方法,其余还是老老实实写Pattern和Matcher把...