正则表达式

2022-05-09 21:11:43 浏览数 (1)


平时用得少,遇到就得到处找。这里总结一下用法,方便复查

1. 正则表达式(regular expression)

描述了字符串的模式匹配,可用于检索、替换、截取符合模式(规则)的串

预习内容:

  • 需正则引擎来进行处理,通常该引擎嵌入程序中(Java正则包嵌到RT里面)
  • 正则会首先返回第一个匹配的串,即使后面还有匹配的模式(急切性)
  • 某些特殊字符需预处理才能传递给引擎( ,*,?),匹配特殊字符要用 转义
  • 匹配 要用 \,Java匹配路径用到正则,那么地址写法有两种:
    • C:\dir\xxx.txt
    • C:/dir/xxx.txt
    • Windows路径用 ,Linux用 /,为了跨平台性推荐使用 / 来写路径
  • 换行符(n)、回车符(r),二者区别类似上世纪打字机,不同系统对换行有不同要求:
    • Windows:rn
    • Linux:n
    • Max:r

2. 正则的组成

  • 普通字符
    • 字母 abcABC
    • 数字 0123
    • 标点符号 , . ?
    • 其他符号
  • 特殊字符(元字符)
    • 非打印字符 r n
    • 限定符 * ?
    • 定位符 ^ $
    • 选择 ( )
    • 反向引用

2.1 非打印字符

字符

描述

.

除换行符 n之外的任意单字符

|

n

换行符

t

回车符

d

数字(digit)

D

除了数字

w

单词(word),数字,大小写字母,下划线

W

非单词

s

空白符(空格,制表符,换页符等)

S

非空白符

2.2 限定符

字符

描述

*

0或多次

1或多次

0或一次

{n}

出现几次

{n, }

至少几次

{n,m}

出现n~m次

2.3 定位符

字符

描述

^

开始

$

结束

b

单词边界(字与空格间的位置)

B

非单词边界

2.4 选择

字符

描述

()

标记子表达式

补充:

  • 字符集[]仅仅匹配里面的其中的一个
  • [^] 表示取反,即不在字符集里面的内容,[^0-9],表示不匹配数字

3. 正则优先级

正则表达式从左到右进行计算,并遵循优先级顺序,下表优先级从高到低

运算符

描述

转义符

()、[]

圆括号、方括号

*、 、?、 {n,m}

限定符

^、$、num

定位符、分组编号

|

替换

4. 匹配模式

修饰符

描述

i

ignore:大小写不敏感

g

global:全局匹配

m

multiline:多行匹配,^$会匹配新行符

s

single:单行匹配,.会匹配新行符

5. 选择 ()

5.1 分组

可将括号内容看成一个整体进行匹配

代码语言:javascript复制
(abc ),表示:abc出现1或多次

5.2 分支

使用分支时要用括号包裹

代码语言:javascript复制
a(b | c | d),表示:ab、ac、ad的其中一个

5.3 分组引用

代码语言:javascript复制
字符串:2020-11-07
模式串:(d{4})-(d{2})-(d{2})
不需要分组引用:(?:d{4})-(d{2})-(d{2}),引用需要缓存降低了速度

引用会把匹配到的组按编号存入缓存,0编号表示整体,后面依次是匹配的内容,使用n来访问分组:

  • 0:2020-11-07
  • 1:2020
  • 2:11
  • 3:07

6. 贪婪和惰性

贪婪是尽可能匹配多的字符,而惰性则是尽可能匹配少的字符(后面加 ? 实现惰性)

6.1 引擎工作原理

代码语言:javascript复制
字符串:<h1>This is H1</h1>
贪婪模式串:<. >
惰性模式串:<. ?>

模式串中:< 匹配该字符,.匹配任意非换行字符, 匹配1或多次前置字符直到换行,>匹配该字符,表示惰性

贪婪流程:

  • <匹配字符串的第一个<
  • .一直匹配前面所有字符,直到最后的换行匹配失败
  • 然后引擎对下一个正则符号匹配,即匹配>,这时会进行回溯,即</h1>的>会被匹配到即立刻急切返回

惰性流程:

  • <匹配字符串的第一个<
  • .匹配h,因为是惰性,所以匹配了.就开启匹配>,尽可能返回少的字符
  • >匹配1失败,就会进行后移,用.继续匹配后面的1,然后重复上面一步
  • 最终返回<h1>

7. 正负向预查

  • xxx(?=pattern):捕获xxx,而xxx是以xxxpattern结尾
  • xxx(?!pattern):上面的否定,即不以pattern结尾
  • (?<=pattern)xxx:捕获xxx,而xxx是以pattern开头
  • (?<!pattern)xxx:上面的否定,即不以pattern开头

8. Java里的正则使用

java.util.regex 包主要包括以下三个类:

  • Pattern:正则表达式的编译表示,不可变类能多线程使用
    • Pattern.compile(reg,flag):表示匹配模式
  • Matcher:是对输入字符串进行解释和匹配操作的引擎
  • PatternSyntaxException:是一个非强制异常类,它表示一个正则表达式模式中的语法错误

8.1 匹配查找

代码语言:javascript复制
public static void main(String[] args) throws InterruptedException {

    String str = "123456789";             // 字符串
    String reg = "\d ";     			  // 模式串

    Pattern pattern = Pattern.compile(reg);
    Matcher matcher = pattern.matcher(str);
    boolean b = matcher.matches();		 // true
}

8.2 捕获组

代码语言:javascript复制
public static void main(String[] args) throws InterruptedException {

    String str = "020-123456";             // 字符串
    String reg = "(\d{3})-(\d{6})";     // 模式串

    Pattern pattern = Pattern.compile(reg);
    Matcher matcher = pattern.matcher(str);

    if(matcher.find()){
        System.out.println(matcher.group(0));	// 020-123456
        System.out.println(matcher.group(1));	// 020
        System.out.println(matcher.group(2));	// 123456
    }
}

8.3 替换

代码语言:javascript复制
public static void main(String[] args) throws InterruptedException {

    String str = "The dog is mine which dog is playing";             // 字符串
    String reg = "dog";                                              // 模式串

    Pattern pattern = Pattern.compile(reg);
    Matcher matcher = pattern.matcher(str);
    String strNew = matcher.replaceAll("cat");
    System.out.println(strNew);			// "The cat is mine which cat is playing"
}

8.4 String类的正则

代码语言:javascript复制
public static void main(String[] args) throws InterruptedException {

    String str = "123456789";             // 字符串
    String reg = "\d ";     			  // 模式串
    
    boolean matches = str.matches(reg);
    System.out.println(matches);		  // true
}

参考:

菜鸟教程

摩诘

0 人点赞