17.Java 正则表达式(正则表达式底层实现、元字符、正则表达式常用类)

server/2024/12/17 1:27:23/

一、正则表达式引入

1、概述
  • 正则表达式(regular expression,简称 RegExp)是处理文本的利器,是对字符串执行模式匹配的技术

  • 例如,使用传统方式提取内容中的所有英文单词就要使用遍历,代码量大,且效率不高,但是正则表达式就可以简化这些操作

2、初体验
  • 提取内容中所有的英文单词
java">String content = "由于在开发Oak语言时,尚且不存在运行字节码的硬件平台,所以为了在开发时可以对这种语言进行实验研究," +"他们就在已有的硬件和软件平台基础上,按照自己所指定的规范,用软件建设了一个运行平台,整个系统除了比C++更加简单之外," +"没有什么大的区别。1992年的夏天,当Oak语言开发成功后,研究者们向硬件生产商进行演示了Green操作系统、Oak的程序设计语言、" +"类库和其硬件,以说服他们使用Oak语言生产硬件芯片,但是,硬件生产商并未对此产生极大的热情。因为他们认为,在所有人对Oak语言" +"还一无所知的情况下,就生产硬件产品的风险实在太大了,所以Oak语言也就因为缺乏硬件的支持而无法进入市场,从而被搁置了下来。";// 1、创建一个 Pattern 对象(模式对象,可以理解成一个正则表达式对象)
Pattern pattern = Pattern.compile("[a-zA-Z]+");// 2、创建一个匹配器对象
// 理解:matcher 按照 pattern 到 content 中去匹配
// 找到就返回 true,未找到就返回 false
Matcher matcher = pattern.matcher(content);// 3、开始循环匹配
while (matcher.find()) {// 匹配到的内容放到 atcher.group(0) 中System.out.println(matcher.group(0));
}
  • 输出结果
Oak
C
Oak
Green
Oak
Oak
Oak
Oak
3、更多演示
  1. 提取内容中所有的数字
java">String content = "由于在开发Oak语言时,尚且不存在运行字节码的硬件平台,所以为了在开发时可以对这种语言进行实验研究," +"他们就在已有的硬件和软件平台基础上,按照自己所指定的规范,用软件建设了一个运行平台,整个系统除了比C++更加简单之外," +"没有什么大的区别。1992年的夏天,当Oak语言开发成功后,研究者们向硬件生产商进行演示了Green操作系统、Oak的程序设计语言、" +"类库和其硬件,以说服他们使用Oak语言生产硬件芯片,但是,硬件生产商并未对此产生极大的热情。因为他们认为,在所有人对Oak语言" +"还一无所知的情况下,就生产硬件产品的风险实在太大了,所以Oak语言也就因为缺乏硬件的支持而无法进入市场,从而被搁置了下来。";Pattern pattern = Pattern.compile("[0-9]+");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
1992
  1. 提取内容中所有的英文单词和数字
java">String content = "由于在开发Oak语言时,尚且不存在运行字节码的硬件平台,所以为了在开发时可以对这种语言进行实验研究," +"他们就在已有的硬件和软件平台基础上,按照自己所指定的规范,用软件建设了一个运行平台,整个系统除了比C++更加简单之外," +"没有什么大的区别。1992年的夏天,当Oak语言开发成功后,研究者们向硬件生产商进行演示了Green操作系统、Oak的程序设计语言、" +"类库和其硬件,以说服他们使用Oak语言生产硬件芯片,但是,硬件生产商并未对此产生极大的热情。因为他们认为,在所有人对Oak语言" +"还一无所知的情况下,就生产硬件产品的风险实在太大了,所以Oak语言也就因为缺乏硬件的支持而无法进入市场,从而被搁置了下来。";Pattern pattern = Pattern.compile("([a-zA-Z]+)|([0-9]+)");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
Oak
C
1992
Oak
Green
Oak
Oak
Oak
Oak
  1. 提取内容中的 IP 地址
java">String content = "10.1.1.1\n" +"\n" +"255.255.0.0\n" +"\n" +"10.1.1.1属于哪个网段?所在网段有多少个IP地址?该网段的广播地址是什么?\n" +"\n" +"答:\n" +"\n" +"10.1.1.1属于10.1.0.0网段。\n" +"\n" +"10.1.0.0网段可用的IP地址范围:10.1.0.1-10.1.255.254(65534)\n" +"\n" +"10.1.1.0网段的广播地址:10.1.255.255";Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+\\.\\d+");
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
10.1.1.1
255.255.0.0
10.1.1.1
10.1.1.1
10.1.0.0
10.1.0.0
10.1.0.1
10.1.255.254
10.1.1.0
10.1.255.255

二、正则表达式底层实现

1、基本介绍
2、案例分析
(0)案例代码
  • 匹配内容中的连续的四个数字
java">String content = "1998年12月8日,第二代Java平台的企业版J2EE发布。1999年6月,Sun公司发布了第二代Java平台(简称为Java2" +")的3个版本:J2ME(Java2 Micro Edition,Java2平台的微型版),应用于移动、无线及有限资源的环境;J2SE" +"(Java 2 Standard Edition,Java 2平台的标准版),3443应用于桌面环境;J2EE(Java 2Enterprise Edition," +"Java 2平台的企业版),应用于基于Java的应用服务器。Java 2平台的发布," +"是Java发展过程中最重要的一个里程碑,9889标志着Java的应用开始普及。";// \\d 表示一个任意数字(0 ~ 9)
String regStr = "\\d\\d\\d\\d";Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
1998
1999
3443
9889
(1)matcher.find()
  1. 根据指定的规则,定位满足规则的字符串

  2. 定位到后,将子字待串的索引记录到 matcher 的属性 int[] groups; 中,例如,1998...,会将子字符串开始的索引记录 groups[0] = 0;,会将子字符串结束的索引 + 1 记录 groups[1] = 4;

  3. 同时记录 oldlast,即子字符串结束的索引 + 1,例如,这里就是 4,记录的作用是下次从这里开始匹配

(2)matcher.group(0)
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();
}
  • 根据 groups[0] 和 groups[1] 的记录,从原字符串开始截取子字符串,左闭右开,这里就是 [0, 4)
3、分组分析
(0)案例代码
java">...String regStr = "(\\d\\d)(\\d\\d)";...while (matcher.find()) {System.out.println(matcher.group(0));System.out.println("第一个分组:" + matcher.group(1));System.out.println("第二个分组:" + matcher.group(2));
}
  • 输出结果
1998
第一个分组:19
第二个分组:98
1999
第一个分组:19
第二个分组:99
3443
第一个分组:34
第二个分组:43
9889
第一个分组:98
第二个分组:89
(1)分组概述
  • 正则表达式里有小括号(())表示分组,第一个小括号表示第一组,第二个小括号表示第二组
(2)matcher.find()
  1. 根据指定的规则,定位满足规则的字符串

  2. 定位到后,将子字待串的索引记录到 matcher 的属性 int[] groups; 中,例如,1998...,会将子字符串开始的索引记录 groups[0] = 0;,会将子字符串结束的索引 + 1 记录 groups[1] = 4;,对第一个分组进行索引记录 groups[2] = 0; groups[3] = 2;,对第二个分组进行索引记录 groups[4] = 2; groups[5] = 4;

  3. 同时记录 oldlast,即子字符串结束的索引 + 1,例如,这里就是 4,记录的作用是下次从这里开始匹配

(3)matcher.group()
  1. matcher.group(0) 表示匹配到的子字符串

  2. matcher.group(1) 表示匹配到的子字符串的第一个分组

  3. matcher.group(2) 表示匹配到的子字符串的第二个分组

  • 注:分组数量不能越界,否则报错

三、元字符

0、转义符
(1)基本介绍
  • 在使用正则表达式去检索某些特殊字符的时候,需要用到转义符(双斜杠,\\),否则检索不到结果,甚至会报错的

  • 注:在其他语言的正则表达式中,转义符是单斜杠(\

  • 如下是需要使用转义符的符号

java">*
+
()
[]
{}
$
/\
?
^
(2)演示
  1. 错误演示
String content = "123(456(";String regStr = "(";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
Exception in thread "main" java.util.regex.PatternSyntaxException: Unclosed group near index 1
(
  1. 使用转义符正确匹配
java">String content = "123(456(";String regStr = "\\(";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
(
(
1、字符匹配符
(1)基本介绍
符号说明示例
[]可接收的字符序列[abcd]:a、b、c、d 中的任意一个字符
[^]可接收的字符序列[^bc]:除 a、b、c 的任意一个字符,包括数字和特殊符号
-连字符A-Z:任意单个大写字面
.匹配除 \n 以外任意字符a..b:以 a 开头,b 结尾,中间包括 2 个任意字符的长度为 4 的字符串
\\d匹配单个数字字符
相当于 [0-9]
\\d{3}(\\d)?:匹配 3 个或 4 个数字的字符串
\\D匹配单个非数字字符\\D(\\d)*:以单个非数字字符开头,后接任意个数字字符串
\\w匹配单个数字和大小写字母字符
相当于 [0-9a-zA-Z]
\\d{3}\\w{4}:以 3 个数字字符开头的长度为 7 的数字字母字符串
\\W匹配单个非数字和大小写字母字符
相当于 [^0-9a-zA-Z]
\\W+\\d{2}:以至少 1 个非数字字母字符开头,2 个数字字符结尾的字符串
(2)演示
  1. 匹配 a - z 之间的任意一个字符([0-9][A-Z] 同理)
java">String content = "a11c8";String regStr = "[a-z]";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
a
c
  1. 不区分大小写匹配
java">String content = "a11c8ABC123abc456Abc";String regStr = "(?i)abc";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
java">// 等同于
String content = "a11c8ABC123abc456Abc";String regStr = "abc";
Pattern pattern = Pattern.compile(regStr, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
示例说明
(?i)abca、b、c 都不区分大小写
a(?i)bcb、c 不区分大小写
a((?i)b)c只有 b 不区分大小写
  • 输出结果
ABC
abc
Abc
  1. 匹配不是 a - z 之间的任意一个字符([0-9][A-Z] 同理)
java">String content = "a11c8";String regStr = "[^a-z]";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
1
1
8
  1. 匹配 a、b、c、d 中的任意一个字符([^abcd] 则是匹配不是 a、b、c、d 中的任意一个字符)
java">String content = "a11c8zyx";String regStr = "[abcd]";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
a
c
  1. 匹配字母、数字、下划线
java">String content = "a11c8zyx&*#@_";String regStr = "\\w";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
a
1
1
c
8
z
y
x
_
  1. 匹配非字母、数字、下划线
java">String content = "a11c8zyx&*#@_";String regStr = "\\W";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
&
*
#
@
  1. 匹配任何空白字符(空格、制表符等)
java">String content = "a1 1c8zy  x&*#@_";String regStr = "\\s";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println("-" + matcher.group(0) + "-");
}
  • 输出结果
- -
- -
- -
  1. 匹配任何非空白字符
java">String content = "a1 1c8zy  x&*#@_";String regStr = "\\S";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
a
1
1
c
8
z
y
x
&
*
#
@
_
  1. 匹配除 \n 之外的所有字符
java">String content = "a1 1cy\n#@_";String regStr = ".";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
a
11
c
y
#
@
_
  1. 匹配 . 自身
java">String content = "a.1 1c.y\n#@_";String regStr = "\\.";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
.
.
2、选择匹配符
(1)基本介绍
符号说明示例
``匹配 `
(2)演示
java">String content = "sunke 孙 helloworld";String regStr = "sunke|孙|hello";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
sunke
孙
hello
3、限定符
(1)基本介绍
  • 限定符用于指定其前面的字符和组合项连续出现多少次
符号说明示例
*指定字符重复 0 次或 n 次(abc)*:包含任意个 abc 的字符串,等效于 \w*
+指定字符重复 1 次或 n 次m+(abc)*:以至少 1 个 m 开头,后接任意个 abc 的字符串
?指定字符重复 0 次或 1 次m+abc?:以至少 1 个 m 开头,后接 ab 或 abc 的字符串
{n}只能输入 n 个字符[abcd]{3}:由 a、b、c、d 组成的任意长度为 3 的字符串
{n,}指定至少 n 个匹配[abcd]{3,}:由 a、b、c、d 组成的任意长度不小于 3 的字符串
{n,m}指定至少 n 个但不多于 m 个匹配[abcd]{3,5}:由 a、b、c、d 组成的任意长度不小于 3 且不大于 5 的字符串
(2)演示
  1. 匹配 1111
java">String content = "11123111123456123";String regStr = "1{4}";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
1111
  1. 匹配两位数字
java">String content = "123abc4567";String regStr = "\\d{2}";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
12
45
67
  1. 匹配 aaa 或 aaaa
  • 注:Java 中的正则匹配默认是贪婪匹配,即尽可能多的匹配
java">String content = "aaaa123123aaa";String regStr = "a{3,4}";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
aaaa
aaa
  1. 匹配一个 1 或多个 1
java">String content = "aaaa123121232341211113aaa";String regStr = "1+";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
1
1
1
1
1111
  1. 匹配 a 后接任意个 1
java">String content = "aaaa123121232341211113aaa";String regStr = "a1*";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
a
a
a
a1
a
a
a
  1. 匹配 a 后接 0 个或 1 个 1
  • 注:遵循贪婪匹配
java">String content = "a1111123121232341211113aaa";String regStr = "a1?";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
a1
a
a
a
4、定位符
(1)基本介绍
  • 定位符规定要匹配的字符串出现的位置,例如,在字符串的开始还是在结束的位置
符号说明示例
^指定起始字符^[0-9]+[a-z]*:以至少 1 个数字开头,后接任意个小写字母的字符串
$指定结束字符^[0-9]\\-[a-z]+$:以 1 个数字开头,后接 -,以至少 1 个小写字母结尾的字符串
\\b匹配原字符串的边界han\\b:这里的边界指的是子串间有空格,或者是原字符串的结束位置
\\B匹配原字符串的非边界-
(2)演示
  1. 以至少 1 个数字开头,后接任意个小写字面
java">String content = "111abc#1ac";String regStr = "^[0-9]+[a-z]*";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
111abc
  1. 以至少 1 个数字开头,以至少 1 个小写字面结尾
java">String content = "111a";String regStr = "^[0-9]+[a-z]+$";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
111a
  1. 匹配边界的 sun
java">String content = "sunke hellosun worldsun";String regStr = "sun\\b";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
sun
sun
  1. 匹配非边界的 sun
java">String content = "sunke hellosun worldsun";String regStr = "sun\\B";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
sun

四、正则表达式其他语法

1、捕获分组
(1)基本介绍
分组形式说明
(【pattern】)非命名捕获,捕获匹配的子字符串
1、编号为 0 的第一个捕获是由整个正则表达式模式匹配的文本
2、其它捕获结果则根据括号的顺序从 1 开始自动编号
(?<【name】>【pattern】)命名捕获,将匹配的子字符串捕获到一个组名称或编号名称中
用于 name 的字符串不能包含任何标点符号,并且不能以数字开头
可以使用单引号替代尖括号,例如,(?'【name】')
(2)演示
  1. 使用非命名捕获,匹配 4 个数字
java">String content = "1231hjkasd879090ad";String regStr = "(\\d\\d)(\\d\\d)";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));System.out.println("第一个分组:" + matcher.group(1));System.out.println("第二个分组:" + matcher.group(2));
}
  • 输出结果
1231
第一个分组:12
第二个分组:31
8790
第一个分组:87
第二个分组:90
  1. 使用命名捕获,匹配 4 个数字
java">String content = "1231hjkasd879090ad";String regStr = "(?<g1>\\d\\d)(?<g2>\\d\\d)";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));System.out.println("第一个分组:" + matcher.group(1));System.out.println("第一个分组:" + matcher.group("g1"));System.out.println("第二个分组:" + matcher.group(2));System.out.println("第二个分组:" + matcher.group("g2"));
}
  • 输出结果
1231
第一个分组:12
第一个分组:12
第二个分组:31
第二个分组:31
8790
第一个分组:87
第一个分组:87
第二个分组:90
第二个分组:90
2、特别分组
(1)基本介绍
分组形式说明
(?:【pattern】)匹配 pattern 但不捕获该匹配的子表达式
它是一个非捕获匹配,不存储供以后使用的匹配
这对于使用 `
(?=【pattern】)它是一个非捕获匹配
例如,`Windows (?=95
(?!【pattern】)它是一个非捕获匹配
该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串
例如,`Windows (?!95
(2)演示
  1. 匹配 “韩顺平教育”、“韩顺平老师”、“韩顺平同学”
java">String content = "hello韩顺平教育 jack韩顺平老师 韩顺平同学hello";// String regStr = "韩顺平教育|韩顺平老师|韩顺平同学";
String regStr = "韩顺平(?:教育|老师|同学)";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));// 不能这么做// System.out.println(matcher.group(1));
}
  • 输出结果
韩顺平教育
韩顺平老师
韩顺平同学
  1. 匹配 “韩顺平教育”、“韩顺平老师” 中的 “韩顺平”
java">String content = "hello韩顺平教育 jack韩顺平老师 韩顺平同学hello";String regStr = "韩顺平(?=教育|老师)";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
韩顺平
韩顺平
  1. 匹配不是 “韩顺平教育”、“韩顺平老师” 中的 “韩顺平”
java">String content = "hello韩顺平教育 jack韩顺平老师 韩顺平同学hello";String regStr = "韩顺平(?!教育|老师)";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
韩顺平
3、非贪婪匹配
(1)基本介绍
  • ? 字符紧随任何其他限定符之后时(*、+、?、{n}、{n,}、{n,m}),匹配模式是非贪婪匹配,非贪婪匹配是匹配搜索到的尽可能短的字符串
(2)演示
java">String content = "sunke123123 hellosun123123 worldsun";String regStr = "\\d+?";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
1
2
3
1
2
3
1
2
3
1
2
3

五、应用实例

1、匹配汉字
java">String content = "你好啊";String regStr = "^[\u0391-\uffe5]+$";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
System.out.println(matcher.find());
2、匹配邮政编码
  • 邮政编码是以 1 ~ 9 开头的 6 位数字
java">String content = "123890";String regStr = "^[1-9]\\d{5}";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
System.out.println(matcher.find());
3、匹配 QQ 号
  • QQ 号是以 1 ~ 9 开头的 5 ~ 10 位数字
java">String content = "2172302933";String regStr = "^[1-9]\\d{4,9}";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
System.out.println(matcher.find());
4、匹配手机号码
  • 手机号码是以 13、14、15、18 开头的 11 位数字
java">String content = "13768528292";String regStr = "^[13|14|15|18]\\d{9}";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
System.out.println(matcher.find());
5、匹配 URL
java">String content = "https://www.bilibili.com/video/BV1Eq4y1E79W?p=17&vd_source=d0beb2b36d04c38a32ed203125b4cbcd";String regStr = "^((http|https)://)([\\w-]+\\.)+[\\w-]+(\\/[\\w-?=&/%#.]*)*$";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
System.out.println(matcher.find());

六、正则表达式常用类

1、基本介绍
  • java.util.regex 包主要包括三个类:Matcher、Pattern、PatternSyntaxException
  1. Pattern:Pattern 对象是一个正则表达式对象,Pattern 类没有公共构造方法,要创建一个 Pattern 对象,需要调用其公共静态方法,该方法接受一个正则表达式作为它的第一个参数

  2. Matcher 类:Matcher 对象是对输入字符串进行解释和匹配的引擎,与Pattern 类一样,Matcher 类也没有公共构造方法,需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象

  3. PatternSyntaxException 类:它是一个非强制异常类,表示一个正则表达式模式中的语法错误

2、Pattern 类常用方法
(1)基本介绍
  • Pattern 类的常用方法是 matches,原码如下,本质还是创建并使用了了 Pattern 对象和 Matcher 对象
java">public static boolean matches(String regex, CharSequence input) {Pattern p = Pattern.compile(regex);Matcher m = p.matcher(input);return m.matches();
}
(2)演示
java">String content = "你好啊";String regStr = "^[\u0391-\uffe5]+$";
boolean res = Pattern.matches(regStr, content);
System.out.println("整体匹配结果:" + res);
3、Matcher 类常用方法
(1)基本介绍
  • 常用方法
方法说明
int start()返回以前匹配的初始索引
int end()返回最后匹配之后的偏移量
boolean find()尝试查找与该模式匹配的输入序列的下一个子序列
boolean matches()尝试将整个区域与模式匹配
public String replaceAll(String replacement)替换模式与给定替换字符串相匹配的输入序列的每个子序列
它不会改变原字符串,会返回新的字符串
(2)演示
  1. start 方法与 end 方法
java">String content = "hello edu jack tom hello smith hello";String regStr = "hello";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println("====================");System.out.println(matcher.start());System.out.println(matcher.end());System.out.println("找到:" + content.substring(matcher.start(), matcher.end()));
}
  • 输出结果
====================
0
5
找到:hello
====================
19
24
找到:hello
====================
31
36
找到:hello
  1. matches 方法
java">String content = "hello edu jack tom hello smith hello";String regStr = "hello.*";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
System.out.println("整体匹配结果:" + matcher.matches());
  • 输出结果
整体匹配结果:true
  1. replaceAll 方法:将”hello”替换成”你好啊“
java">String content = "hello edu jack tom hello smith hello";String regStr = "hello";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
String newContent = matcher.replaceAll("你好啊");
System.out.println(newContent);
  • 输出结果
你好啊 edu jack tom 你好啊 smith 你好啊

七、反向引用

1、基本使用
  • 给你一段文本,请你找出所有四个数字连在一起的子串,并且这四个数字要满足第 1 位与第 4 位相同,第 2 位与第 3 位相同

  • 要解决该问题,需要了解正则表达式的几个概念

  1. 分组:用圆括号(())组成一个比较复杂的匹配模式,一个圆括号的部分可以看作是一个子表达式(一个分组)

  2. 捕获:把正则表达式中子表达式(分组)匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用,从左向右,以分组的左括号为标志,第一个出现的分组的组号为 1,第二个为 2,以此类推,组 0 代表的是整个正则式

  3. 反向引用:圆括号的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,这样的方式被称为反向引用,这种引用既可以是在正则表达式内部,也可以是在正则表达式外部,内部反向引用为 \\【分组号】,外部反向引用为 $【分组号】

2、演示
  1. 匹配两个连续的相同数字
java">String content = "hello 11 edu 22 jack 34 tom 1234 hello 55 smith 666 hello";String regStr = "(\\d)\\1";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
11
22
55
66
  1. 匹配五个连续的相同数字
java">String content = "hello 11111 edu 22222 jack 34 tom 1234 hello 55 smith 666 hello";// String regStr = "(\\d)\\1\\1\\1\\1";
String regStr = "(\\d)\\1{4}";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
11111
22222
  1. 匹配第 1 位与第 4 位相同,第 2 位与第 3 位相同的数字
java">String content = "hello 21121 edu 22222 jack 34 tom 1221 hello 55 smith 666 hello";String regStr = "(\\d)(\\d)\\2\\1";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {System.out.println(matcher.group(0));
}
  • 输出结果
2112
2222
1221
  1. 结巴去重问题
java">String content = "我...要要...学学 Java";// 1、去掉所有的点
Pattern pattern = Pattern.compile("\\.");
Matcher matcher = pattern.matcher(content);
content = matcher.replaceAll("");// 2、去重,将重复 N 次的字替换成 1 个字
// 因为正则表达式的变化,所以需要重置 matcher
pattern = Pattern.compile("(.)\\1+");
matcher = pattern.matcher(content);
content = matcher.replaceAll("$1");System.out.println(content);
  • 输出结果
我要学 Java

八、String 类的正则支持

1、基本介绍
  1. String 类的 public String replaceAll(String regex, String replacement),支持正则替换,它不会改变原字符串,会返回新的字符串

  2. public boolean matches(String regex) 支持正则匹配

  3. public String[] split(String regex) 支持正则分割

2、演示
  1. 替换 JDK1.3 和 JDK1.4 为 JDK
java">String content = "2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。";content = content.replaceAll("JDK\\d.\\d", "JDK");System.out.println(content);
  • 输出结果
2000年5月,JDK、JDK和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。
  1. 验证一个手机号,必须以 138 或 139 开头
java">String content = "13877791234";System.out.println(content.matches("^13(?:8|9)\\d{8}"));
  • 输出结果
true
  1. 按”=“、”&“、”#“、”$“分割
java">String content = "sunke=123123&hello#sun&123$123";String[] resArr = content.split("=|#|\\$|&");
for (String s : resArr) {System.out.println(s);
}
  • 输出结果
sunke
123123
hello
sun
123
123

http://www.ppmy.cn/server/150767.html

相关文章

es有string类型字段吗

在较新的版本的 Elasticsearch (ES) 中,string 类型已经被移除,取而代之的是更具体的 text 和 keyword 类型。这一改变是在 Elasticsearch 5.0 版本引入的,目的是为了提供更好的性能和更明确的数据处理方式。 Text 类型 用途:text 类型用于全文搜索。当你有一个字段需要进…

【工具】linux matlab 的使用

问题1 - 复制图表 在使用linux matlab画图后&#xff0c;无法保存figure。 例如在windows下 但是在linux下并没有这个“Copy Figure”的选项。 这是因为 “ The Copy Figure option is not available on Linux systems. Use the programmatic alternative.” 解决方案&…

《Vue进阶教程》第十课:其它函数

往期内容&#xff1a; 《Vue零基础入门教程》合集&#xff08;完结&#xff09; 《Vue进阶教程》第一课&#xff1a;什么是组合式API 《Vue进阶教程》第二课&#xff1a;为什么提出组合式API 《Vue进阶教程》第三课&#xff1a;Vue响应式原理 《Vue进阶教程》第四课&#…

架构13-持久化存储

零、文章目录 架构13-持久化存储 1、Kubernetes 存储设计 &#xff08;1&#xff09;存储设计考量 **设计哲学&#xff1a;**Kubernetes 遵循用户通过资源和声明式 API 描述意图&#xff0c;Kubernetes 根据意图完成具体操作。**复杂性&#xff1a;**描述用户的存储意图本身…

【MySQL】深度学习数据库开发技术:使用C/C++语言访问数据库

前言&#xff1a;本节内容介绍使用C/C访问数据库&#xff0c; 包括对数据库的增删查改操作。 主要是学习一些接口的调用&#xff0c; 废话不多说&#xff0c; 开始我们的学习吧&#xff01; ps:本节内容比较容易&#xff0c; 友友们放心观看哦&#xff01; 目录 准备mysql库 …

docsify

macos ➜ ~ node -v v16.20.2➜ ~ npm --version 8.19.4全局安装 docsify-cli 工具 npm i docsify-cli -g➜ ~ docsify -vdocsify-cli version:4.4.4初始化项目 docsify init ./docsls -ah docs . .. .nojekyll README.md index.htmlindex.html 入口文件README.md 会…

【Stream流】

1.体验Stream流【理解】 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素把集合中所有以"张"开头的元素存储到一个新的集合把"张"开头的集合中的长度为3的元素存储到一个新的集合遍历上一步得到的集合 原始方式…

大模型呼入机器人的缺点是什么?(转)

大模型呼入机器人的缺点是什么&#xff1f;(转) 原作者&#xff1a;开源呼叫中心FreeIPCC&#xff0c;其Github&#xff1a;https://github.com/FreeIPCC/FreeIPCC 大模型呼入机器人在提供高效、自动化服务的同时&#xff0c;也存在一些缺点。以下是对其缺点的详细归纳&#…