常用常新:正则表达式在Java中的基本使用

242 阅读3分钟

常用常新:正则表达式在Java中的基本使用

一 概念

正则表达式是对字符串操作的一种逻辑公式,就是用普通字符和有特殊意义的特殊字符两种的组合,组成一个“规则字符串“,这个“规则字符串”用来表达对字符串的一种过滤逻辑。说白了正则是用来专门处理字符串的工具,日常操作字符串要时时刻刻想到它。

二 用途

  • 匹配判断:给定的字符串是否符合正则的过滤逻辑,例如我们最常用的手机、邮箱等的校验;

  • 获取处理:可以通过正则,从字符串中获取我们想要的特定部分,并进行操作处理,例如字符串提取、分割、模板替换等;

三 字符种类

既然正则是由字符串组成,那首先要识别它的组成部分,知道每个字符代表什么意思。这里简单分下类。

3.1 普通字符

1-9 a-z A-Z _ - @ & } ]等,数字、大小写字母、还有一些字符在正则中代表其本身。也就是1就是1,@就是@,没有什么特殊含义。

3.1 特殊字符

^ $ | . * + ? \ ( ) { [ 等,某些特殊字符在正则中具有特殊含义,具有特定的功能。例如.用来表示任意的一个字符。此时若想使用使用特殊字符其本身,可使用转义字符\,例如.要写作\.|要写作\|

这里值得注意的是小括号( )前后都是特殊字符,中括号和大括号前一半[ {是特殊字符,后一半] }则是普通字符。

3.1 组合字符

\d \w 等,这种特定字符通过多个字符组合而成,也表示一种特殊含义,如\d代表数字。

四 反斜杠数量问题

在Java日常使用中一直被反斜杠\的数量问题搞的懵逼,时有时没有,一会两个、一会又四个。懵逼的主要原因有二:

一 、搞不清或搞混了字符含义,尤其认识不到哪些字符在正则中是特殊字符需要转义。

二 、在Java中\也是特殊符号(转义字符),想要表示其原义就要多使用一个\转义。 所以\在Java中表示原义就要写成\\

理清楚这两个原因,数量问题也就不难搞懂了。例如在Java中正则里的一个\居然需要四个写作\\\\

Java中要表示一个反斜杠符号本身就要转义一次,写作\\,又因为\正则中本身也是特殊字符,需要转义,两个反斜杠再各转一次就变成四个了。

        String s="123abc_123_2132";
        String s1="123abc|123|2132";
        String s2="123abc1232132";
        String s3="123|abc.123%2132";
        String s4="123\\abc\\123\\2132";
        // _替换为@
        System.out.println( s.replaceAll("_","@"));
        // |替换为@
        System.out.println( s1.replaceAll("\\|","@"));
        // 所有数字都替换为@
        System.out.println( s2.replaceAll("\\d","@"));
        // 将・ | % 都替换为@
        System.out.println( s3.replaceAll("[\\|\\.%]","@"));
        // 反斜杠替换
        System.out.println( s4.replaceAll("\\\\","@"));
-------------------------------------------------------------
        123abc@123@2132
        123abc@123@2132
        @@@abc@@@@@@@
        123@abc@123@2132
        123@abc@123@2132

五 一般匹配

5.1 单字符匹配

字符含义
^正则字符开头
$正则字符结尾
.任意的一个字符
\d数字
\D非数字
\w字符、数字、下划线
\W非(字符、数字、下划线)
\s空格和tab字符(\t)
\S非空格和tab字符(\t)
\n换行符
\r回车符
\u548c指定Unicode字符

5.2 字符集匹配(范围匹配)

字符含义
[]匹配方括号中定义的字符集之一
[^]字符集否定匹配,匹配没有在方括号中定义的字符
[a-zA-Z]只匹配字母
[1-8]只匹配1到8的数字
[abc]只匹配a或b或c中一个

5.3 多次匹配(重复匹配)

单字符匹配和字符集匹配都只能匹配到一个字符,可结合多次匹配以达到匹配字符串的目的。

字符含义
*0到n次匹配
0到1次匹配
+1到n次匹配
{n,}匹配n次以上
{n,m}匹配n到m次

5.4 或匹配

多个正则之间|隔开。弥补字符集匹配只能针对字符的缺点。

字符含义
java|python子表达式中可以使用单字符和字符集
        String s2="python_js_java_go";
        System.out.println(s2.replaceAll("java|js","nb"));
        ---------------------------------------------
        python_nb_nb_go

5.5 子段匹配

一长串正则表达式中一部分作为一个独立的子正则,使用()定义子表达式。

字符含义
([abc]\d+)子表达式中可以使用单字符和字符集
(){1,2}子表达式也可以结合次数规则

5.6 综合练习

这里练习一个判断字符串是否是数字(包含整数、小数)的正则。

  1. 写一个判断是否是整数的 [0-9]+,表示数字至少出现1次;

  2. 如果后面是小数的话则有小数点,加上\\.?,小数点可有可无且需要转义,此时

变为[0-9]+\\.?;

  1. 小数点后面数字同样为[0-9]+此时变为[0-9]+\\.?[0-9]+

  2. 负数需要加上负号-?变为-?[0-9]+\.?[0-9]+

  3. 此时还差一步,字符为0时判断错误。

  4. 如何解决?把小数点及后面数字当作一个子正则,整数无,小数有。此时正则变为

    -?[0-9]+(\\.?[0-9]+)?

  5. 补上正则开始结束符号最终为^-?[0-9]+(\\.?[0-9]+)?$

六 基本使用场景

  • 最常用的使用PatternMatcher对象来进行判断操作

  • String对象的spiltreplaceAll方法也可直接使用正则

        // 判断是否是数字
        Pattern pattern = Pattern.compile("^-?[0-9]+(\\.?[0-9]+)?$");
        System.out.println(pattern.matcher("123").matches());// true
        System.out.println(pattern.matcher("-212").matches());// true
        System.out.println(pattern.matcher("12.1234").matches());// true
        System.out.println(pattern.matcher("-46.1234").matches());// true
        System.out.println(pattern.matcher("0").matches());// true