阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

匹配规则

27次阅读
没有评论

共计 3259 个字符,预计需要花费 9 分钟才能阅读完成。

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

对于正则表达式 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 这种简单的规则暂时做不到,我们需要更复杂规则,后面会详细讲解。

小结

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

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

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

正则表达式 规则 可以匹配
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

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计3259字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中