正则表达式
★第二十二章 正则表达式
Regular Expression
:正则表达式,是对字符串执行模式匹配的技术。
正则表达式快速入门
下面是正则表达式快速入门的例子,对字符串文本中的英文单词进行匹配输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36package com.f.chapter22.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author fzy
* @date 2023/8/15 19:08
* 正则表达式快速入门例子
*/
public class RegExp01 {
public static void main(String[] args) {
//要处理的字符串文本
String content = "1995年,互联网的蓬勃发展给了Oak机会。业界为了使死板、单调的静态网页能够“灵活”起来," +
"急需一种软件技术来开发一种程序,这种程序可以通过网络传播并且能够跨平台运行。" +
"于是,世界各大IT企业为此纷纷投入了大量的人力、物力和财力。这个时候,Sun公司想起了那个被搁置起来很久的Oak," +
"并且重新审视了那个用软件编写的试验平台,由于它是按照嵌入式系统硬件平台体系结构进行编写的,所以非常小," +
"特别适用于网络上的传输系统,而Oak也是一种精简的语言,程序非常小,适合在网络上传输。" +
"Sun公司首先推出了可以嵌入网页并且可以随同网页在网络上传输的Applet" +
"(Applet是一种将小程序嵌入到网页中进行执行的技术),并将Oak更名为Java。" +
"5月23日,Sun公司在Sun world会议上正式发布Java和HotJava浏览器。" +
"IBM、Apple、DEC、Adobe、HP、Oracle、Netscape和微软等各大公司都纷纷停止了自己的相关开发项目," +
"竞相购买了Java使用许可证,并为自己的产品开发了相应的Java平台。";
//1.先创建一个Pattern对象, 即模式对象, 可以理解为就是一个正则表达式对象, 传入的参数为正则表达式
Pattern pattern = Pattern.compile("[a-zA-Z]+"); //要匹配英文单词
//2.创建一个匹配器对象, 传入要处理的字符串
// matcher 匹配器按照 pattern(模式/样式) 到 content 文本中去匹配。
Matcher matcher = pattern.matcher(content);
//3.开始循环匹配
while (matcher.find()) { //如果找到就返回 true,否则返回 false。
//匹配到的内容可以通过 matcher.group 得到
System.out.println("找到: " + matcher.group(0));
}
}
}
★正则表达式底层原理
matcher.find()
matcher.find()
完成的任务:根据指定的正则表达式,定位满足规则的子字符串。
找到后,将子字符串 “开始的索引位置” 记录到
matcher
对象的属性int[] groups
中。“开始的索引位置” 记录到
groups[0]
中。同时将子字符串 “结束的索引位置 + 1” 记录到
gropus
中。“结束的索引位置 + 1” 记录到
groups[1]
中。同时记录
oldLast
的值为 “结束的索引位置 + 1”,即下次执行find
方法时,就从oldLast
开始继续向下匹配。
matcher.group(0)
matcher.group(0)
用来返回匹配到的内容:1
2
3
4
5
6
7
8
9public String group(int group) {
if (first < 0)
throw new IllegalStateException("No match found");
if (group < 0 || group > groupCount())
throw new IndexOutOfBoundsException("No group " + group);
if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
return null;
return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}根据
groups[0]
和groups[1]
记录的位置,从字符文本中截取子字符串 (截取规则为左闭右开的规则) 并返回。以下面的代码为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60package com.f.chapter22.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author fzy
* @date 2023/8/15 19:29
* 分析Java正则表达式的底层实现
*/
public class RegExpTheory {
public static void main(String[] args) {
//给定一段字符串,找出所有四个数字连在一起的子串
String content = "2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。" +
"2001年9月24日,J2EE1.3发布。2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升,与J2SE1.3相比," +
"其多了近62%的类和接口。在这些新特性当中,还提供了广泛的XML支持、安全套接字(Socket)支持(通过SSL与TLS协议)、" +
"全新的I/OAPI、正则表达式、日志与断言。2004年9月30日,J2SE1.5发布,成为Java语言发展史上的又一里程碑。" +
"为了表示该版本的重要性,J2SE 1.5更名为Java SE 5.0(内部版本号1.5.0),代号为“Tiger”," +
"Tiger包含了从1996年发布1.0版本以来的最重大的更新,其中包括泛型支持、基本类型的自动装箱、改进的循环、枚举类型、" +
"格式化I/O及可变参数。";
//正则表达式, 匹配四个数字连在一起的子串
//说明: \\d 表示一个任意的数字
String regExp = "\\d\\d\\d\\d";
//1.先创建一个Pattern对象, 即模式对象, 可以理解为就是一个正则表达式对象, 传入的参数为正则表达式
Pattern pattern = Pattern.compile(regExp);
//2.创建一个匹配器对象, 传入要处理的字符串
// matcher 匹配器按照 pattern(模式/样式) 到 content 文本中去匹配。
Matcher matcher = pattern.matcher(content);
//3.开始循环匹配
/*
* matcher.find() 完成的任务
* (1)根据指定的正则表达式,定位满足规则的子字符串
* (2)找到后,将子字符串 “开始的索引位置” 记录到 matcher 对象的属性 int[] groups 中
* 以第一个找到的 2000 为例,groups[0] = 0 (因为2的索引位置为0)
* 同时将子字符串 “结束的索引位置 + 1” 记录到 groups 中
* 以第一个找到的 2000 为例,groups[1] = 4 (因为最后一个0的索引位置为3,3+1=4)
* (3)同时记录 oldLast 的值为 “结束的索引位置 + 1”,即下次执行 find 方法时,就从 oldLast 开始继续向下匹配
* */
while (matcher.find()) { //如果找到就返回 true,否则返回 false。
//匹配到的内容可以通过 matcher.group 得到
/**
* public String group(int group) {
* if (first < 0)
* throw new IllegalStateException("No match found");
* if (group < 0 || group > groupCount())
* throw new IndexOutOfBoundsException("No group " + group);
* if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
* return null;
* return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
* }
* (1)根据 groups[0] 和 groups[1] 记录的位置,从 content 中截取子字符串(截取规则为左闭右开的规则)并返回
* 以第一个找到的 2000 为例,groups[0] = 0,groups[1] = 4,所以返回的就是 "2000"
* (2)然后继续向下匹配,将会匹配到 2001,此时会更新 groups[0] 和 groups[1] 的值,即更新后
* groups[0] = 65,groups[1] = 69,所以返回的就是 "2001"
* 同样的,oldLast 的值也会进行更新
*/
System.out.println("找到: " + matcher.group(0));
}
}
}
★matcher.group(i)
正则表达式另外还有分组的概念。将上面的代码改写一下,以下面代码为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69package com.f.chapter22.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author fzy
* @date 2023/8/15 21:56
* 分析Java正则表达式的底层实现(引入分组)
*/
public class RegExpTheory2 {
public static void main(String[] args) {
String content = "2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。" +
"2001年9月24日,J2EE1.3发布。2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升,与J2SE1.3相比," +
"其多了近62%的类和接口。在这些新特性当中,还提供了广泛的XML支持、安全套接字(Socket)支持(通过SSL与TLS协议)、" +
"全新的I/OAPI、正则表达式、日志与断言。2004年9月30日,J2SE1.5发布,成为Java语言发展史上的又一里程碑。" +
"为了表示该版本的重要性,J2SE 1.5更名为Java SE 5.0(内部版本号1.5.0),代号为“Tiger”," +
"Tiger包含了从1996年发布1.0版本以来的最重大的更新,其中包括泛型支持、基本类型的自动装箱、改进的循环、枚举类型、" +
"格式化I/O及可变参数。";
//分组:例如下面的 (\\d\\d)(\\d\\d),正则表达式中有 () 就表示分组,第一个 () 代表第一组,第二个 () 代表第二组
String regExp = "(\\d\\d)(\\d\\d)";
//1.先创建一个Pattern对象, 即模式对象, 可以理解为就是一个正则表达式对象, 传入的参数为正则表达式
Pattern pattern = Pattern.compile(regExp);
//2.创建一个匹配器对象, 传入要处理的字符串
// matcher 匹配器按照 pattern(模式/样式) 到 content 文本中去匹配。
Matcher matcher = pattern.matcher(content);
//3.开始循环匹配
/*
* matcher.find() 完成的任务 (考虑分组)
* (1)根据指定的正则表达式,定位满足规则的子字符串
* (2)找到后,将子字符串 “开始的索引位置” 记录到 matcher 对象的属性 int[] groups 中
* 同时将子字符串 “结束的索引位置 + 1” 记录到 groups 中
* (2.1)仍以第一个找到的 2000 为例,groups[0] = 0 (因为2的索引位置为0),groups[1] = 4 (因为最后一个0的索引位置为3,3+1=4)
* 但是因为引入了分组,所以还会将第一组 (对应20)、第二组 (对应00) 的开始和结束索引位置也记录下来
* (2.2)第一组匹配到的字符串 (20),groups[2] = 0 (因为2的索引位置为0),groups[3] = 2 (因为20的最后一个0的索引位置为1,1+1=2)
* (2.3)第二组匹配到的字符串 (00),groups[4] = 2 (因为第一个0的索引位置为2),groups[5] = 4 (因为第二个0的索引位置为4,3+1=4)
* 如果有更多的分组,以此类推...
* (3)同时记录 oldLast 的值为 “结束的索引位置 + 1”,即下次执行 find 方法时,就从 oldLast 开始继续向下匹配
* */
while (matcher.find()) { //如果找到就返回 true,否则返回 false。
//匹配到的内容可以通过 matcher.group 得到
/**
* public String group(int group) {
* if (first < 0)
* throw new IllegalStateException("No match found");
* if (group < 0 || group > groupCount())
* throw new IndexOutOfBoundsException("No group " + group);
* if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
* return null;
* return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
* }
* (1)根据 groups[0] 和 groups[1] 记录的位置,从 content 中截取子字符串(截取规则为左闭右开的规则)并返回
* 以第一个找到的 2000 为例,groups[0] = 0,groups[1] = 4,所以返回的就是 "2000"
* 因为引入了分组,所以还可以得到匹配到的子字符串的分组的内容
* matcher.group(0) 表示得到 groups[0] 和 groups[1] 所对应的子字符串,即表示返回匹配到的子字符串的所有内容。
* matcher.group(1) 表示得到 groups[2] 和 groups[3] 所对应的子字符串,即表示返回匹配到的子字符串的第 `1` 个分组的内容。
* matcher.group(2) 表示得到 groups[4] 和 groups[5] 所对应的子字符串,即表示返回匹配到的子字符串的第 `2` 个分组的内容。
* 以此类推...
* 从 return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString(); 也可以看出来
* (2)然后继续向下匹配,将会匹配到 2001,此时会更新 groups[0] 和 groups[1] 的值,即更新后
* groups[0] = 65,groups[1] = 69,所以返回的就是 "2001",其分组也和上面类似
* 同样的,oldLast 的值也会进行更新
*/
System.out.print("找到匹配内容: " + matcher.group(0) + "\t");
System.out.print("匹配内容的第一组: " + matcher.group(1) + "\t");
System.out.println("匹配内容的第二组: " + matcher.group(2));
}
}
}- 上面代码注释中比较重要的一句话:
但是因为引入了分组,所以还会将第一组 (对应20)、第二组 (对应00) 的开始和结束索引位置也记录下来
。 - 从上面的代码可以看出来,
matcher.group(i)
表示返回匹配到的子字符串的第i
个分组的内容。matcher.group(0)
表示返回匹配到的子字符串的所有内容。matcher.group(1)
表示返回匹配到的子字符串的第1
个分组的内容。matcher.group(2)
表示返回匹配到的子字符串的第2
个分组的内容。- ……
- 上面代码注释中比较重要的一句话:
★★★正则表达式语法
- 如果要想灵活的运用正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:
- 特殊字符。
- 字符匹配符。
- 选择匹配符。
- 限定符。
- 定位符。
- 分组组合和反向引用符。
★转义符 \
- 注意:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号
"\"
,否则检索不到结果,甚至报错。例如,用"\("
匹配左括号而不是"("
。- 同时,**在
Java
的正则表达式中,用两个"\\"
代表其他语言的一个"\"
**,所以在Java
中,用"\\("
匹配左括号。 - 需要用到转义符号的字符有以下:
. * + ( ) $ / \ ? [ ] ^ { } |
,当要找到这些字符它们 “本身” 时,需要用到转义符号。
- 同时,**在
- 注意:在
[]
中匹配特殊字符时,不需要用到转义符号,例如[.]
表示要匹配的就是.
字符本身。
★字符匹配符
符号 | 符号 | 示例 | 解释 |
---|---|---|---|
[] | 可接收的字符列表 | [efgh] | e、f、g、h中的任意一个字符 |
[^] | 不可接收的字符列表 | [^abc] | 除a、b、c之外的任意一个字符,包括数字和特殊符号 |
- | 连字符 | A-Z | 任意单个大写字母 |
. | 匹配除 \n 以外的任何字符 | a..b | 以a开头,b结尾,中间包括2个任意字符的长度为4的字符串 |
\\d | 匹配单个数字字符,相当于[0-9] | \\d{3}(\\d)? | 包含3个或4个数字的字符串 |
\\D | 匹配单个非数字字符,相当于[^0-9] | \\D(\\d)* | 以单个非数字字符开头,后接任意个数字字符串 |
\\w | 匹配单个数字、大小写字母字符和下划线,相当于[0-9a-zA-Z_] | \\d{3}\\w{4} | 以3个数字字符开头的长度为7的数字字母下划线字符串 |
\\W | 匹配单个非数字、大小写字母字符、下划线,相当于[^0-9a-zA-Z_] | \\W+\\d{2} | 以至少1个非数字字母下划线字符开头,2个数字字符结尾的字符串 |
\\s | 匹配任何空白字符(空格、制表符等) | ||
\\S | 匹配任何非空白字符,和 \\s 刚好相反 |
Java
正则表达式默认是区分字母大小写的,可以通过使用(?i)
的方式实现不区分大小写:(?i)abc
表示abc
都不区分大小写。a(?i)bc
表示bc
不区分大小写。a((?i)b)c
表示只有b
不区分大小写。
也可以通过在创建
Pattern
对象时,指定Pattern.CASE_INSENSITIVE
实现不区分大小写:Pattern pattern = Pattern.compile(regExp, Pattern.CASE_INSENSITIVE);
选择匹配符 |
- 在匹配某个字符串的时候是选择性的,即:既可以匹配这个,又可以匹配那个,这时你需要用到选择匹配符号
|
。
符号 | 符号 | 示例 | 解释 |
---|---|---|---|
**` | `** | **匹配 `” | “` 之前或之后的表达式** |
★限定符
- 用于指定其前面的字符和组合项连续出现多少次。
符号 | 符号 | 示例 | 解释 |
---|---|---|---|
* | 指定字符重复0次或n次(无要求) | (abc)* | 仅包含任意个abc的字符串 |
+ | 指定字符重复1次或n次(至少一次) | m+(abc)* | 以至少1个m开头,后接任意个abc的字符串 |
? | 指定字符重复0次或1次(最多一次) | m+abc? | 以至少1个m开头,后接ab或abc的字符串 |
{n} | 只能输入n个字符 | [abcd]{3} | 由abcd中字母组成的任意长度为3的字符串 |
{n,} | 指定至少n个匹配 | [abcd]{3,} | 由abcd中字母组成的任意长度不小于3的字符串 |
{n,m} | 指定至少n个但不多于m个匹配 | [abcd]{3,5} | 由abcd中字母组成的任意长度不小于3,不大于5的字符串 |
- ★注意:
Java
正则表达式匹配默认是贪婪匹配,会尽可能多地匹配。例如:- 对于正则表达式
1*
和要匹配的字符串11111
,在匹配时,会优先匹配11111
而不是其他的,比如空
、1
、11
等。 - 对于正则表达式
1+
和要匹配的字符串11111
,在匹配时,会优先匹配11111
而不是其他的,比如1
、11
等。 - 对于正则表达式
a1?
和要匹配的字符串a11111
,在匹配时,会优先匹配a1
而不是a
。 - 对于正则表达式
a{3,5}
和要匹配的字符串aaaaa
,在匹配时,会优先匹配aaaaa
而不是aaa
或者aaaa
。
- 对于正则表达式
定位符
- 定位符,规定要匹配的字符串出现的位置,比如在字符串的开始还是在结束的位置。
符号 | 符号 | 示例 | 解释 |
---|---|---|---|
^ | 指定起始字符 | ^[0-9]+[a-z]* | 以至少1个数字开头,后接任意个小写字母的字符串 |
$ | 指定结束字符 | ^[0-9]\-[a-z]+$ | 以1个数字开头后接连字符 “-“,并以至少1个小写字母结尾的字符串 |
\\b | 匹配目标字符串的边界 | han\b | 这里说的字符串的边界指的是子串间有空格的地方,或者是字符串的开始或结束位置 |
\\B | 匹配目标字符串的非边界 | han\B | 和 \b 的含义相反 |
分组
捕获分组
常用分组构造形式 | 说明 |
---|---|
(pattern) | 非命名捕获。捕获匹配的子字符串。编号为零的第一个捕获是由整个正则表达式模式匹配的文本,其它捕获结果则根据左括号的顺序从1开始自动编号。 |
(?<name>pattern) | 命名捕获。将匹配的子字符串捕获到一个组名称或编号名称中。用于name的字符串不能包含任何标点符号,并且不能以数字开头。可以使用单引号替代尖括号,例如 (?'name') 代替 (?<name>) |
1 | package com.f.chapter22.regexp; |
非捕获分组
常用分组构造形式 | 说明 |
---|---|
(?:pattern) | 匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这**对于用 "or" 字符 (`” |
(?=pattern) | 它是一个非捕获匹配。例如,`’Windows (?=95 |
(?!pattern) | 该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配。例如,`’Windows (?!95 |
1 | package com.f.chapter22.regexp; |
★反向引用
反向引用和分组、捕获之间是有关系的,所以下面再重述一次分组和捕获的概念:
- 分组:我们可以用圆括号组成一个比较复杂的匹配模式,那么一个圆括号的部分我们可以看作是一个子表达式 / 一个分组。
- 捕获:把正则表达式中的子表达式 / 分组匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用,从左向右,以分组的左括号为标志,第一个出现的分组的组号为 1 ,第二个为 2 ,以此类推。组 0 代表的是整个正则式。
- 反向引用:圆括号的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,这个我们称为反向引用,这种引用既可以是在正则表达式内部,也可以是在正则表达式外部,**内部反向引用
\\分组号
,外部反向引用$分组号
**。
反向引用的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.f.chapter22.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author fzy
* @date 2023/8/18 11:59
* 反向引用例子
*/
public class RegExp04 {
public static void main(String[] args) {
String content = "hello, world123443222221!";
//String regExp = "(\\d)\\1"; //要匹配两个连续的相同数字
//String regExp = "(\\d)\\1{4}"; //要匹配五个连续的相同数字
String regExp = "(\\d)(\\d)\\2\\1"; //要匹配个位与千位相同、十位与百位相同的数字
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
}
★非贪婪匹配 ?
- 当此字符
?
紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})
之后时,匹配模式是 “非贪心的”。**”非贪心的” 模式匹配搜索到尽可能短的匹配的字符串,而默认的 “贪心的” 模式匹配搜索到尽可能长的匹配字符串。**例如,在字符串"oooo"
中,"o+?"
只匹配单个"o"
,而"o+"
匹配所有"o"
。
正则表达式常用类
Pattern
pattern
对象是一个正则表达式对象。Pattern
类没有公共构造方法。要创建一个Pattern
对象需要调用其公共静态方法compile
,它返回一个Pattern
对象。该方法接受一个正则表达式作为它的第一个参数。Pattern
的常用方法如下代码所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package com.f.chapter22.pattern;
import org.junit.jupiter.api.Test;
import java.util.regex.Pattern;
/**
* @author fzy
* @date 2023/8/18 10:45
* Pattern类的常用方法演示
*/
public class PatternMethod {
//1.matches方法,用于整体匹配,在验证输入的字符串是否满足条件时使用,
// 满足时返回true,否则返回false
/**
* public static boolean matches(String regex, CharSequence input) {
* Pattern p = Pattern.compile(regex);
* Matcher m = p.matcher(input);
* return m.matches();
* }
* 底层调用的是 Matcher 类的 matches 方法
*/
public void patternMatches() {
String content = "hello, world!";
String regExp = "hello.*";
boolean matches = Pattern.matches(regExp, content);
System.out.println("整体匹配为: " + matches);
}
}
Matcher
Matcher
对象是对输入字符串进行解释和匹配的引擎。与Pattern
类一样,Matcher
也没有公共构造方法。你需要调用Pattern
对象的matcher
方法来获得一个Matcher
对象。Matcher
类的常用方法如下所示:方法及说明 public int start()
:返回以前匹配的初始索引。public int start(int group)
:返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引。public int end()
:返回最后匹配字符之后的偏移量。public int end(int group)
:返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。public boolean lookingAt()
:尝试将从区域开头开始的输入序列与该模式匹配。public boolean find()
:尝试查找与该模式匹配的输入序列的下一个子序列。public boolean find(int start)
:重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。public boolean matches()
:尝试将整个区域与模式匹配。public String replaceAll(String replacement)
:将与给定模式相匹配的输入序列的每个子序列替换为给定的字符串。方法返回的才是替换后的结果。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37package com.f.chapter22.matcher;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author fzy
* @date 2023/8/18 11:00
* Matcher类的常用方法演示
*/
public class MatcherMethod {
public static void main(String[] args) {
//要匹配的内容
String content = "hello, world! hello smith";
//指定的正则表达式
String regExp = "hello";
//1.创建pattern对象
Pattern pattern = Pattern.compile(regExp);
//2.创建matcher对象
Matcher matcher = pattern.matcher(content);
//3.得到匹配结果
while (matcher.find()) {
System.out.println("============");
//(1)`public int start()`:返回以前匹配的初始索引。
System.out.println("匹配的内容的开始索引 = " + matcher.start());
//(2)`public int end()`:返回最后匹配字符之后的偏移量。
System.out.println("匹配的内容的结束索引 + 1 = " + matcher.end());
}
System.out.println();
//(3)`public String replaceAll(String replacement)`:将与给定模式相匹配的输入序列的每个子序列替换为给定的字符串。方法返回的才是替换后的结果。
// 将上面内容中的 hello 替换为 hi
String newContent = matcher.replaceAll("hi");
System.out.println(content); //hello, world! hello smith
System.out.println(newContent); //hi, world! hi smith
}
}
String类中使用正则表达式
1 | package com.f.chapter22.regexp; |