什么是正则?

正则就是对文本进行 匹配、查询、替换和提取字符串 的一种处理工具

1 功能介绍

  • 匹配和验证: 例如对邮箱、手机号等数据的验证,快速匹配是否满足格式;
  • 搜索和替换文本: 可以用正则文本中是否包含指定字符串,并可对其进行替换为其他数据;
  • 数据提取 : 可以通过正则提取文本中的网址、手机号、邮箱等特定规则数据;
  • 自动化处理:可用于自动化处理文本,自动生成代码,或批量文件命名等操作。

1.1 示例

使用正则进行手机号验证

private static void matchPhoneLength(){  
    String phone = "110";  
    //匹配手机号长度  
    boolean matches = phone.matches("\\d{11}");  
    System.out.println(matches);//false  
  
    String phone1 = "11111111111";  
    //匹配手机号长度  
    boolean matches1 = phone1.matches("\\d{11}");  
    System.out.println(matches1);//true  
}

2 使用

Stringmatches 提供了正则的匹配,参数为正则表达式。

2.1 匹配任意字符

. 表示匹配任意字符。

System.out.println("a1b".matches("a.b"));//true  
System.out.println("abb".matches("a.b"));//true  
System.out.println("a¥b".matches("a.b"));//true  
System.out.println("ab".matches("a.b"));//false

2.2 匹配空格

\\s 可以匹配空格字符及tab 字符( JAVA 中 tab 用 \t 表示 )。

System.out.println(" ".matches("\\s"));//true  
System.out.println("\t".matches("\\s"));//true  
System.out.println("a".matches("\\s"));//false

2.3 模糊匹配

JAVA\ 表示转义字符,而正则是使用 \\d,D,w,W 等表示特殊匹配; 如 \\d 表示匹配数据 0-9\w 匹配字母、下划线及数字等,\\D 匹配非数据,\\W 匹配非字母、下划线及数字。

private static void matchNumberAndLetter(){  
    //匹配数字  
    System.out.println("1".matches("\\d"));//true  
    System.out.println("a".matches("\\d"));//false  
    //匹配字母,数字,下划线  
    System.out.println("a".matches("\\w"));//true  
    System.out.println("1".matches("\\w"));//true  
    System.out.println("_".matches("\\w"));//true  
    System.out.println(".".matches("\\w"));//false  
}

警告

正则中 \\d,\\W 这类代码,出现一次只能匹配一次,若字符串中有多个字符,需要重复使用才能匹配所有数据如 "12".matches("\\d\\d"),或使用重复匹配符。

2.4 重复匹配符

    • : 匹配前一个字符或组 0 次或多次(即“可有可无,但可以有多个”)
    • : 匹配前一个字符或组 1 次或多次(即“至少出现一次”)。
  • ? : 匹配前一个字符或组 0 次或 1 次(即“可选的单个字符”)。
  • 匹配指定次数:通过 {次数} 来实现, 如果需匹配一个区间使用 {次数,次数} 进行匹配。
private static void matchCount(){  
    System.out.println("123".matches("\\d*"));//true >0  
    System.out.println("1ab".matches("\\d+"));//false =1  
    System.out.println("123".matches("\\d+"));//true  
    System.out.println("abc".matches("\\d?"));//false  
    System.out.println("12".matches("\\d?"));//false  
    System.out.println("123".matches("\\d{2}"));//false  
    System.out.println("123".matches("\\d{3}"));//true  
    boolean matches = phone.matches("\\d{3,4}-\\d{7,8}");  //最少匹配三位,最多匹配四位
	System.out.println(matches);//true
}

2.5 总结

2.5.1 单字符匹配

正则表达式规则可以匹配
A指定字符A
\u548c指定Unicode字符
.任意字符ab&0
\d数字0~90~9
\w大小写字母,数字和下划线azAZ0~9_
\s空格、Tab键空格,Tab
\D非数字aA&_,……
\W非\w&@,……
\S非\saA&_,……

2.5.2 多字符匹配

正则表达式规则可以匹配
A*任意个数字符空,AAAAAA,……
A+至少1个字符AAAAAA,……
A?0个或1个字符空,A
A{3}指定个数字符AAA
A{2,3}指定范围个数字符AAAAA
A{2,}至少n个字符AAAAAAAAA,……
A{0,3}最多n个字符空,AAAAAA

3 复杂匹配

3.1 匹配开头和结尾

正则对多行进行匹配时,^ 表示开头,& 表示结尾

System.out.println("a12b".matches("^a.+b$"));// true  
System.out.println("aabsb".matches("^a.+b$"));// true  
System.out.println("aa".matches("^a.+b$"));// false

3.2 匹配指定范围

[...] 可以匹配指定范围内的字符,如匹配字符是否在 [1-3] 内。

//第二位是数字且小于5  
System.out.println("a2".matches(".[0-4].*"));  //true
System.out.println("a6".matches(".[0-4].*"));  // false
System.out.println("a2".matches(".[01234].*"));  //true
System.out.println("a6".matches(".[01234].*")); // false

3.3 或规则匹配

| 连接的两个规则是 规则,AB|CD 表示既可以匹配 AB 也可以匹配 CD

System.out.println("1".matches("1|2"));//true  
System.out.println("2".matches("1|2"));//true

3.4 使用括号

当想要匹配 learn javalearn phplearn go 时,规则可并行为 learn\sjava|learn\sphp|learn\sgo 也可以使用括号对规则进行优化: learn\s(java|php|go) 提取公共部分用括号括起来。

//括号提取  
String regex = "learn\\s(java|php|go)";  
System.out.println("learn java".matches(regex));//true  
System.out.println("learn php".matches(regex));//true  
System.out.println("learn go".matches(regex));//true

3.5 总结

正则表达式规则可以匹配
^开头字符串开头
$结尾字符串结束
[ABC][…]内任意字符A,B,C
[A-F0-9xy]指定范围的字符A,……,F0,……,9xy
[^A-F]指定范围外的任意字符A~F
AB|CD|EFAB或CD或EFABCDEF

4 分组匹配

引用

前文提到用 (...) 提取子串进行匹配,实际还有一种作用,可用在分组匹配中。

4.1 例如

要将一个电话号码 012-12345678 先进行正则验证,后对子串进行拆分区号和号码。

//数据规则匹配  
String str = "012-12345678";  
System.out.println(str.matches("\\d{3,4}-\\d{7,8}"));//true  
//分组匹配  
String regex = "(\\d{3,4})-(\\d{7,8})";  
Pattern compile = Pattern.compile(regex);  
Matcher matcher = compile.matcher(str);  
if (matcher.matches()){  
    System.out.println(matcher.group(1));//012  
    System.out.println(matcher.group(2));//12345678  
    System.out.println(matcher.group(0));//012-12345678  
}

如果要根据正则规则对文本进行分组,需先使用 (...) 将需分组的规则包围起来,然后引入 Patten 对象进行匹配。

4.2 Pattern

使用 String.matches() 方法进行多次匹配,复用率低。而使用 Pattern 对象可以反复使用实现编译一次,多次匹配。

import java.util.regex.*;
 
public class Main {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
        pattern.matcher("010-12345678").matches(); // true
        pattern.matcher("021-123456").matches(); // false
        pattern.matcher("022#1234567").matches(); // false
        // 获得Matcher对象:
        Matcher matcher = pattern.matcher("010-12345678");
        if (matcher.matches()) {
            String whole = matcher.group(0); // "010-12345678", 0表示匹配的整个字符串
            String area = matcher.group(1); // "010", 1表示匹配的第1个子串
            String tel = matcher.group(2); // "12345678", 2表示匹配的第2个子串
            System.out.println(area);
            System.out.println(tel);
        }
    }
}

==使用 Matcher 时,必须首先调用 matches() 判断是否匹配成功,匹配成功后,才能调用 group() 提取子串。==