添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

正则表达式的匹配规则是从左到右按规则匹配。我们首先来看如何使用正则表达式来做精确匹配。

对于正则表达式 abc 来说,它只能精确地匹配字符串 "abc" ,不能匹配 "ab" "Abc" "abcd" 等其他任何字符串。

如果正则表达式有特殊字符,那就需要用 \ 转义。例如,正则表达式 a\&c ,其中 \& 是用来匹配特殊字符 & 的,它能精确匹配字符串 "a&c" ,但不能匹配 "ac" "a-c" "a&&c" 等。

要注意正则表达式在Java代码中也是一个字符串,所以,对于正则表达式 a\&c 来说,对应的Java字符串是 "a\\&c" ,因为 \ 也是Java字符串的转义字符,两个 \\ 实际上表示的是一个 \

// regex
public class Main {
    public static void main(String[] args) {
        String re1 = "abc";
        System.out.println("abc".matches(re1));
        System.out.println("Abc".matches(re1));
        System.out.println("abcd".matches(re1));
        String re2 = "a\\&c"; // 对应的正则是a\&c
        System.out.println("a&c".matches(re2));
        System.out.println("a-c".matches(re2));
        System.out.println("a&&c".matches(re2));

如果想匹配非ASCII字符,例如中文,那就用\u####的十六进制表示,例如:a\u548cc匹配字符串"a和c",中文字符的Unicode编码是548c

匹配任意字符

精确匹配实际上用处不大,因为我们直接用String.equals()就可以做到。大多数情况下,我们想要的匹配规则更多的是模糊匹配。我们可以用.匹配一个任意字符。

例如,正则表达式a.c中间的.可以匹配一个任意字符,例如,下面的字符串都可以被匹配:

  • "abc",因为.可以匹配字符b
  • "a&c",因为.可以匹配字符&
  • "acc",因为.可以匹配字符c
  • 但它不能匹配"ac""a&&c",因为.匹配一个字符且仅限一个字符。

    .可以匹配任意字符,这个口子开得有点大。如果我们只想匹配0~9这样的数字,可以用\d匹配。例如,正则表达式00\d可以匹配:

  • "007",因为\d可以匹配字符7
  • "008",因为\d可以匹配字符8
  • 它不能匹配"00A""0077",因为\d仅限单个数字字符。

    匹配常用字符

    \w可以匹配一个字母、数字或下划线,w的意思是word。例如,java\w可以匹配:

  • "javac",因为\w可以匹配英文字符c
  • "java9",因为\w可以匹配数字字符9;。
  • "java_",因为\w可以匹配下划线_
  • 它不能匹配"java#""java ",因为\w不能匹配#、空格等字符。

    匹配空格字符

    \s可以匹配一个空格字符,注意空格字符不但包括空格 ,还包括tab字符(在Java中用\t表示)。例如,a\sc可以匹配:

  • "a c",因为\s可以匹配空格字符
  • "a c",因为\s可以匹配tab字符\t
  • 它不能匹配"ac""abc"等。

    匹配非数字

    \d可以匹配一个数字,而\D则匹配一个非数字。例如,00\D可以匹配:

  • "00A",因为\D可以匹配非数字字符A
  • "00#",因为\D可以匹配非数字字符#
  • 00\d可以匹配的字符串"007""008"等,00\D是不能匹配的。

    类似的,\W可以匹配\w不能匹配的字符,\S可以匹配\s不能匹配的字符,这几个正好是反着来的。

    // regex
    public class Main {
        public static void main(String[] args) {
            String re1 = "java\\d"; // 对应的正则是java\d
            System.out.println("java9".matches(re1));
            System.out.println("java10".matches(re1));
            System.out.println("javac".matches(re1));
            String re2 = "java\\D";
            System.out.println("javax".matches(re2));
            System.out.println("java#".matches(re2));
            System.out.println("java5".matches(re2));
    

    我们用\d可以匹配一个数字,例如,A\d可以匹配"A0""A1",如果要匹配多个数字,比如"A380",怎么办?

    修饰符*可以匹配任意个字符,包括0个字符。我们用A\d*可以匹配:

  • A:因为\d*可以匹配0个数字;
  • A0:因为\d*可以匹配1个数字0
  • A380:因为\d*可以匹配多个数字380
  • 修饰符+可以匹配至少一个字符。我们用A\d+可以匹配:

  • A0:因为\d+可以匹配1个数字0
  • A380:因为\d+可以匹配多个数字380
  • 但它无法匹配"A",因为修饰符+要求至少一个字符。

    修饰符?可以匹配0个或一个字符。我们用A\d?可以匹配:

  • A:因为\d?可以匹配0个数字;
  • A0:因为\d?可以匹配1个数字0
  • 但它无法匹配"A380",因为修饰符?超过1个字符就不能匹配了。

    如果我们想精确指定n个字符怎么办?用修饰符{n}就可以。A\d{3}可以精确匹配:

  • A380:因为\d{3}可以匹配3个数字380
  • 如果我们想指定匹配n~m个字符怎么办?用修饰符{n,m}就可以。A\d{3,5}可以精确匹配:

  • A380:因为\d{3,5}可以匹配3个数字380
  • A3800:因为\d{3,5}可以匹配4个数字3800
  • A38000:因为\d{3,5}可以匹配5个数字38000
  • 如果没有上限,那么修饰符{n,}就可以匹配至少n个字符。

    请编写一个正则表达式匹配国内的电话号码规则:3~4位区号加7~8位电话,中间用-连接,例如:010-12345678

    // regex
    import java.util.*;
    public class Main {
        public static void main(String[] args) throws Exception {
            String re = "\\d";
            for (String s : List.of("010-12345678", "020-9999999", "0755-7654321")) {
                if (!s.matches(re)) {
                    System.out.println("测试失败: " + s);
                    return;
            for (String s : List.of("010 12345678", "A20-9999999", "0755-7654.321")) {
                if (s.matches(re)) {
                    System.out.println("测试失败: " + s);
                    return;
            System.out.println("测试成功!");
    

    进阶:国内区号必须以0开头,而电话号码不能以0开头,试修改正则表达式,使之能更精确地匹配。

    提示:\d\D这种简单的规则暂时做不到,我们需要更复杂规则,后面会详细讲解。

    单个字符的匹配规则如下:

    正则表达式