MJ: Java正则表达式
提取文章中所有的 英文单词 / 数字 / 或者单词数字
如果按照我们对字符串的操作满足上面的要求, 工作量会很大; 这时我们就需要使用 正则表达式
当我们对字符串或文本进行过滤/提取, 就需要使用正则表达式; 正则表达式是处理文本的利器
为了解决上面的问题, Java提供了正则表达式技术, 专门用于处理类似的问题; 简单的说: 正则表达式是对字符串执行模式匹配的技术
正则表达式 — regular expression — RegExp
正则表达式是对字符串执行模式匹配的技术
一个正则表达式, 就是用
某种模式去匹配字符串的一个公式
; 一旦掌握正则表达式, 之前花费几小时而且容易出错的文本处理工作缩短在几分钟内完成。
public class Regexp01 {
@Test
public void test01() {
// 正则表达式, 模式匹配, 根据提供的文本内容, 一个字符一个字符进行模式匹配
String content = "1998年12月8日,第二代Java平台的企业版J2EE发布。";
//1. 先创建一个Pattern对象, 模式对象 --> 正则表达式对象
// ----提取文章中所有的英文单词----
// Pattern pattern = Pattern.compile("[a-zA-Z]+");
// ----提取文章中所有的数字----
// Pattern pattern = Pattern.compile("[0-9]+");
// ----提取文章中所有的英文单词和数字----
Pattern pattern = Pattern.compile("([0-9]+)|([a-zA-Z]+)");
//2. 创建匹配器对象;
Matcher matcher = pattern.matcher(content);
//3. 开始循环匹配. 找到就返回true, 否则返回false
while (matcher.find()) {
// 匹配内容,文本,放到m.group(0)中
System.out.println("找到:" + matcher.group(0));
}
}
找到:1998
找到:12
找到:8
找到:Java
找到:J
找到:2
找到:EE
@Test
public void test02() {
String content = "\n" +
" 国家卫健委:疫苗接种遵循自愿原则\n" +
" ";
//1. 先创建一个Pattern对象, 模式对象 --> 正则表达式对象
Pattern pattern = Pattern.compile(");
//2. 创建匹配器对象;
Matcher matcher = pattern.matcher(content);
//3. 开始循环匹配. 找到就返回true, 否则返回false
while (matcher.find()) {
System.out.println("找到:" + matcher.group(1));
}
}
找到:国家卫健委:疫苗接种遵循自愿原则
@Test
public void test03() {
String content = "私有地址(Private address)属于非注册地址,专门为组织机构内部使用。\n" +
"以下列出留用的内部私有地址\n" +
"A类 10.0.0.0--10.255.255.255\n" +
"B类 172.16.0.0--172.31.255.255\n" +
"C类 192.168.0.0--192.168.255.255";
//1. 先创建一个Pattern对象, 模式对象 --> 正则表达式对象
Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+\\.\\d+");
//2. 创建匹配器对象;
Matcher matcher = pattern.matcher(content);
//3. 开始循环匹配. 找到就返回true, 否则返回false
while (matcher.find()) {
System.out.println("找到:" + matcher.group(0));
}
}
找到:10.0.0.0
找到:10.255.255.255
找到:172.16.0.0
找到:172.31.255.255
找到:192.168.0.0
找到:192.168.255.255
}
/**
* Description: 分析Java的正则表达式的底层实现(重要)
*
* @date 2022/3/27 09:22
*/
public class Regexp02 {
@Test
public void test01() {
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平台的企5775业版),应用于1568基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个里程碑,标志着Java的应用开始普及6886。";
// 目标:匹配所有四个数字
// 说明
// 1.\\d代表任意一个数字
String regStr = "(\\d\\d)(\\d\\d)";
// 2.创建模式对象(及正则表达式)
Pattern pattern = Pattern.compile(regStr);
// 3.创建匹配器
// 说明:创建匹配器matcher,按照 正则表达式的规律 去匹配 content字符串
Matcher matcher = pattern.matcher(content);
// 4.开始匹配
/*
* matcher.find() 完成的任务 (考虑分组)
* 什么是分组,比如 (\d\d)(\d\d), 正则表达式中有() 表示分组,第1个()表示第1组,第2个()表示第2组...
* 1.根据指定的规则,定位满足规则的子字符串(比如1998)
* 2.找到后,将 子字符串的索引记录到matcher对象的属性 int[] groups;
* 2.1 groups[0] = 0,把该子字符串的结束的索引+1 的值记录到 groups[1] = 4
* 2.2 记录1组()匹配到的字符串 groups[2] = 0 groups[3] = 2
* 2.3 记录2组()匹配到的字符串 groups[4] = 2 groups[5] = 4
* 2.4 如果有更多的分组.....
* 3.同时记录oldLast 的值为 子字符串的结束的 索引+1的值即为4,即下次执行find时, 就从4开始匹配
*
* 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();
}
* 1.根据groups[0]=0 和 groups[1] = 4 的记录的位置,从content开始截取子字符串返回
* 就是[0,4) 包含0 但是不包含索引为4的位置
*
* 1.根据groups[0]=31 和 groups[1] = 35 的记录的位置,从content开始截取子字符串返回
* 就是[31,35) 包含0 但是不包含索引为35的位置
*
* 如果再次指向find方法,仍然按上面分析来执行
* */
while (matcher.find()) {
// 小结
// 1.如果正则表达式有() 即分组
// 2.取出匹配的字符串规则如下
// 3.group(0) 表示匹配到的子字符串
// 4.group(1) 表示匹配到的子字符串的第1组子串
// 5.group(2) 表示匹配到的子字符串的第2组子串
// 6. ... 但是分组的树不能越界
System.out.println("找到:" + matcher.group(0));
System.out.println("第1组()匹配到的值=" + matcher.group(1));
System.out.println("第2组()匹配到的值=" + matcher.group(2));
}
}
}
找到:1998
第1组()匹配到的值=19
第2组()匹配到的值=98
找到:1999
第1组()匹配到的值=19
第2组()匹配到的值=99
找到:3443
第1组()匹配到的值=34
第2组()匹配到的值=43
找到:5775
第1组()匹配到的值=57
第2组()匹配到的值=75
找到:1568
第1组()匹配到的值=15
第2组()匹配到的值=68
找到:6886
第1组()匹配到的值=68
第2组()匹配到的值=86
如果想灵活的运用正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:
在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号
\\
,否则检索不到结果; 需要转义的字符:( [ { / ^ - $ ¦ } ] ) ? * + .
*表示0个或多个 ?表示0个或1个 +表示1个或n个
注意: 下面通过: 定义content, regStr, pattern, matcher, matcher.find()等; 不是完全匹配; 而是判断并输出content中是否有符合regStr规则的子串; content中的内容是按字符从左到右匹配
- 后面我们会学到matches()方法, 返回类型为boolean, 该方法为完全匹配。
// 写的正则表达式regStr是否匹配content中符合规则的子串, 并返回子串
public class Regexp03 {
// 转义字符测试
@Test
public void test01() {
String content = "A1234abc$(a.bc(a12b323(";
//String regStr = "\\(";
//String regStr = "\\."; // 等同于[.]
//String regStr = "\\d{3}"; // 匹配连续3个数字的子串,相当于\\d\\d\\d // 123 323
//String regStr = "a..b"; // a12b 注意: .可以匹配任何非\n的字符
//String regStr = "\\d{3}(\\d)?"; // ?表示0/1, 该表达式意思为匹配连续3个或4个的字符数字
//String regStr = "\\D(\\d)*"; // 以单个非数字字符开头,后接任意个数字字符串; *表示0个或多个 ?表示0个或1个 +表示1个或n个
//String regStr = "[.]"; // 根据.来匹配, 在[]中的. ?都不需要转义
//String content = "a";
//String regStr = "a?"; //结果: "a" [0,1) 和 "" [1, 1) 可以匹配一个空串,因为空串也符合0次; ? 表示0次或1次
String regStr = "[bc]{2}"; // 相当于[bc][bc], [bc]是单字符匹配符,[bc]一次只能出现b或c; 所以匹配的内容可以是bb bc cc
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
找到: bc
找到: bc
}
public class Regexp04 {
@Test
public void test01() {
String content = "@a11c8a bcABCy_ ";
//String regStr = "[a-z]"; // 匹配a-z中的任意字符
//String regStr = "[A-Z]"; // 匹配A-Z中的任意字符
//String regStr = "abc"; // 匹配abc子串
//String regStr = "(?i)abc"; // 匹配abc/ABC子串,大小写不敏感; a(?i)bc表示bc不区分大小写; a((?i)b)c表示b不区分大小写
//String regStr = "[0-9]"; // 匹配0到9之间的数字
//String regStr = "[^a-z]"; // 匹配非a-z中的字符, 1 8
//String regStr = "[^a-z]{2}"; // 匹配非a-z中的字符,且为连续的2个字符; 11
//String regStr = "[^0-9]{3}"; // 匹配非0-9的字符,且连续3个字符; abc ABC
//String regStr = "[^abcd]"; // 匹配非abcd中字符的
//String regStr = "\\D{3}"; // \\D和[^0-9]等价; \\d和[0-9]等价
//String regStr = "\\w"; // 匹配 字母,数字,下划线 等价 [0-9a-zA-Z_]
//String regStr = "\\W"; // 匹配非 字母,数字,下划线 等价 [^0-9a-zA-Z_]
//String regStr = "\\s"; // 匹配任何空白字符
//String regStr = "\\S"; // 匹配任何非空白字符
String regStr = "."; // 匹配出\n之外的所有字符, 如果要匹配. 本身要使用转义\\.
//Pattern pattern = Pattern.compile(regStr, Pattern.CASE_INSENSITIVE); // Pattern.CASE_INSENSITIVE也表示对大小写不敏感
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
}
[abc]等价于 [a|b|c]等价于(a|b|c)
@Test
public void test() {
String content = "zhangsanfeng 张 章";
String regStr = "zhang|张|章";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
找到: zhang
找到: 张
找到: 章
字符
和组合项
连续出现多少次public class Regexp05 {
@Test
public void test02() {
String content = "1111111aaaahello";
//String regStr = "a{3}"; // 等价aaa, 匹配aaa
//String regStr = "1{4}"; // 表示匹配1111
//String regStr = "\\d{2}"; // 表示出现连续2位的数字, 11 11 11
//String regStr = "a{3,4}"; // 表示匹配aaa或aaaa; 细节: java匹配默认是贪婪匹配, 尽可能匹配多的 aaaa
//String regStr = "1{4,5}"; // 11111
String regStr = "\\d{2,5}"; // 表示匹配2位数或3,4,5位数的连续数字; 先返回11111, 再返回 11; 贪婪匹配
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
@Test
public void test03() {
String content = "a1111111aaaahello222";
//String regStr = "1+"; // 匹配一个1或者多个1; 贪婪匹配
//String regStr = "\\d+"; // 匹配一个或多个数字
//String regStr = "1*"; // 匹配0个1或多个1
String regStr = "a1?"; // 匹配a 或 a1; ?表示零个或多个
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
}
// 贪婪
@Test
public void test06() {
String content = "afooaaaaaafooa";
/*
分析:
1.贪婪规则:
先吞掉整个content进行匹配, 若匹配失败, 则吐出最后一个字符;再次匹配,重复该过程,直到匹配成功
afooaaaaaafooa匹配失败, 然后吐出a, content=afooaaaaaafoo 匹配成功
2.题目分析:默认是贪婪的
.*foo这个表达式, *表示0或n个, 而.*表示1个或1+n个. 也就是可以匹配n个任意字符; 后面foo表示以foo结尾
找到的结果为: afooaaaaaafoo
但是观察发现content前4个字符afoo也符合.*foo表达式,为什么没有找到呢?
因为表达式默认是贪婪的, 会将整个content吞掉进行匹配
*/
String regStr = ".*foo";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
//找到 afooaaaaaafooa
}
// 勉强
@Test
public void test07() {
String content = "afooaaaaaafooa";
/*
分析:
先吞掉一个字符进行匹配, 若匹配失败, 则吞掉下一个字符再尝试匹配, 重复此过程,直到成功
a不匹配; af不; afo不; afoo匹配成功, 此时content=aaaaaafooa 然后继续重复该流程
a不; aa不; .....; aaaaaafoo匹配成功
*/
String regStr = ".*?foo";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
//找到: afoo
//找到: aaaaaafoo
}
// 独占
@Test
public void test08() {
String content = "afooaaaaaafooa";
/*
分析:
规则: 吞掉整个input进行唯一一次匹配(不常用)
*/
String regStr = ".*+foo";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
//找不到
}
@Test
public void test() {
String content = "123-abc";
//String regStr = "[0-9]+[a-z]*"; // 匹配至少1个数字,后接任意个小写字母的字符串
//String regStr = "^[0-9]+[a-z]*"; // 必须以至少1个数字开头,后接任意个小写字母的字符串
//String regStr = "^[0-9]+[a-z]+$"; // 必须至少1个数字开头,后接必须至少1个小写字母结束
String regStr = "^[0-9]+\\-[a-z]+$"; // 必须至少1个数字开头,后接必须至少1个小写字母结束
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
找到: 123-abc
}
@Test
public void test10() {
String content = "hello world hihello youhello uhellohello";
// 上面三个hello后面都有空格, 所以找到3个hello,又因为最后一个hello在结束位置,所以也能匹配最后一个hello
//String regStr = "hello\\b"; //找到: hello //表示匹配边界的hello(这里的边界是指:被匹配的字符串最后,也可以是空格的子字符串的后面)
// 这里匹配机制和\\b相反,能匹配到倒数第二个hello
String regStr = "hello\\B"; //找到:hello 找到:hello //和\\b的含义刚好相反
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
String regex1 = "dog{3}";
"doggg".matches(regex1); // true
// [dog]等价于[d|o|g]等价于(d|o|g)
String regex2 = "[dog]{3}"; //等价 [dog][dog][dog]; 而[dog]每次只能取其中一个字符, 所以有27种可能
"ddd".matches(regex2); // true
"ooo".matches(regex2); // true
"ggg".matches(regex2); // true
"dog".matches(regex2); // true
"gog".matches(regex2); // true
"gdo".matches(regex2); // true
// ... 共 3 * 3 * 3 = 27 种可能
// (dog)就是一个捕获组
String regex3 = "(dog){3}"; //等价(dog)(dog)(dog); 而(dog)是一个整体; 所以(dog){3}完全匹配dogdogdog
"dogdogdog".matches(regex3); // true
// 非命名分组
@Test
public void test01() {
String content = "hanshunping s7789 nn1189han";
//下面是非命名分组:
//说明:
//1.matcher.group(0)得到匹配到的字符串
//2.matcher.group(1)得到匹配到的字符串的第一个分组内容
//3.matcher.group(2)得到匹配到的字符串的第二个分组内容
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("第1个分组内容= " + matcher.group(1));
System.out.println("第2个分组内容= " + matcher.group(2));
System.out.println("第3个分组内容= " + matcher.group(3));
}
}
找到: 7789
第1个分组内容= 77
第2个分组内容= 8
第3个分组内容= 9
找到: 1189
第1个分组内容= 11
第2个分组内容= 8
第3个分组内容= 9
// 命名分组
@Test
public void test02() {
String content = "hanshunping s7789 nn1189han";
// 命名分组: 可以给分组取名
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("第1个分组内容= " + matcher.group(1));
System.out.println("第2个分组内容= " + matcher.group(2));
System.out.println("第1个(命名)分组内容= " + matcher.group("g1"));
System.out.println("第2个(命名)分组内容= " + matcher.group("g2"));
}
}
找到: 7789
第1个分组内容= 77
第2个分组内容= 89
第1个(命名)分组内容= 77
第2个(命名)分组内容= 89
找到: 1189
第1个分组内容= 11
第2个分组内容= 89
第1个(命名)分组内容= 11
第2个(命名)分组内容= 89
/**
* 非捕获分组
*/
@Test
public void test03() {
String content = "hello 程序员教育 jack 程序员老师 程序员同学";
//String regStr = "程序员教育|程序员老师|程序员同学";
// 上面的写法可以等价非捕获分组,不能matcher.group(1)
// String regStr = "程序员(?:教育|老师|同学)"; // 返回: 程序员教育 程序员老师 程序员同学
//目标: 找到程序员这个关键字,但是要求只是查找程序员教育和程序员老师 中包含有的程序员
//String regStr = "程序员(?=教育|老师)"; // 返回: 程序员 程序员
//目标: 找到程序员同学中的程序员, 返回它的程序员
String regStr = "程序员(?!教育|老师)"; // 返回: 程序员
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
Java中默认是贪婪匹配 (可看上面介绍的贪婪、勉强、独占)
public class Regexp07 {
@Test
public void test() {
String content = "hello111111 ok";
String regStr = "\\d+"; // + 表示1个或n个1匹配, 默认采用贪婪匹配, 匹配n个1 // 111111 无空子串
// 如果上面不想使用贪婪匹配,可以加?
//String regStr = "\\d*"; // 贪婪匹配; 111111 有空子串
//String regStr = "\\d?"; // 非贪婪匹配; 1 1 1 1 1 1
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
}
/**
* Description: 正则表达式的应用实例
*
* @date 2022/3/27 14:23
*/
public class Regexp08Test {
@Test
public void test() {
//1. 验证是否是汉字
//String content = "张三丰";
//String regStr = "^[\u0391-\uffe8]+$";
//2. 邮政编码, 1-9开头的六位数
String content = "123890";
String regStr = "^[1-9]\\d{5}$";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
System.out.println("满足格式: " + matcher.group(0));
} else {
System.out.println("不满足格式!");
}
}
@Test
public void test02() {
// QQ号: 要求1-9开头的(5位-10位数)
String content = "123890";
String regStr = "^[1-9]\\d{4,9}$";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("满足格式: " + matcher.group(0));
}
}
@Test
public void test03() {
// 手机号;要求以 13, 14, 15, 18开头的11位数
String content = "14839905434";
String regStr = "^1[3|4|5|8]\\d{9}$";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("满足格式: " + matcher.group(0));
}
}
@Test
public void test04() {
// URL验证
String content = "https://www.bilibili.com/blackboard/activity-TVWStSTDRs.html?spm_id_from=333.851.b_62696c695f7265706f72745f6c697665.21";
/*
思路:
1. 先确定url的开始部分 https:// | http://
2. 通过([\w-]+\.)+[\w-]+ 匹配 www.bilibili.com
3. (/[\\w-?=&/%.#]*)? 中 ?表示可能0个或1个; [\\w-?=&/%.#]* 表示: 0个或多个[\\w-?=&/%.#]; [\\w-?=&/%.#]表示 可以出现0-9a-zA-Z中的字符和-?=&/%.#
*/
String regStr = "^((https|http)://)?([\\w-]+\\.)+[\\w-]+(/[\\w-?=&/%.#]*)?$";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("满足格式: " + matcher.group(0));
}
}
}
Pattern类
:pattern对象是一个正则表达式对象,Pattern类没有公共构造方法,创建一个Pattern对象,需要调用公共静态方法compile,它返回一个Pattern对象,该方法接受一个正则表达式作为它的第一个参数。Matcher类
:Matcher对象是对输入字符串进行解释和匹配的引擎。与Pattern类一样,Matcher也没有构造方法,你需要调用Pattern对象的matcher方法来获得一个Matcher对象。Pattern类中的matches()方法
注意: matches方法是完全匹配, 也就是说写的表达式regStr 必须整体匹配 content的内容, 否则返回false
@Test
public void test() {
String content = "hello abc hello, 王大小";
//String regStr = "hello"; // false
String regStr = "hello.*"; // 表示hello后除\n可以跟任意字符
boolean matches = Pattern.matches(regStr, content);
System.out.println("整体匹配: matches = " + matches); // true
}
@Test
public void test01() {
String content = "hello edu jack tom hello smith hello";
String regStr = "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()));
System.out.println("找到: " + matcher.group(0));
}
// 整体匹配
System.out.println(matcher.matches()); // false
}
@Test
public void test02() {
// 将content中的hello替换为你好
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 = " + newContent);
System.out.println("content = " + content);
}
/**
* Description: 反向引用
* @date 2022/3/28 13:17
*/
public class Regexp10 {
@Test
public void test() {
String content = "hello33333 jack13317887 tom11 jack22 yyy12345 xxx";
//String regStr = "(\\d)\\1"; // 匹配两个连续的相同数字
//String regStr = "(\\d)\\1{4}"; // 匹配五个连续的相同数字
String regStr = "(\\d)(\\d)\\2\\1"; // 匹配个位和千位相同, 十位和百位相同的数 5225, 1221等
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
@Test
public void test01() {
String content = "12345-11122233327372-999888777";
// 满足前面是一个五位数, 然后一个-号, 后面是一个九位数,连续每三位相同
String regStr = "\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到: " + matcher.group(0));
}
}
@Test
public void test02() {
String content = "我...我要...学学学Java编编程!";
// 首先替换掉.
content = Pattern.compile("\\.").matcher(content).replaceAll("");
// 我我要学学学Java编编程!
// (.)表示匹配字符串中非\n的每一个字符;\\1表示每一个字符后面是否有和自己相同的字符; +表示有1个或n个和自己相同的字符
String regStr = "(.)\\1+"; // 这个+针对于 学学学 这种情况; 如果是 要 就没有效果,因为(.)\\1都匹配不上
// 和这个 $1 就是外部引用 满足匹配 (.)中的字符, 1为分组号
System.out.println(Pattern.compile(regStr).matcher(content).replaceAll("$1"));
}
}
public String replaceAll(String regex, String replacement)
public boolearn matches(String regex)
底层使用Pattern和Matcher类public String[] split(String regex)
@Test
public void test03() {
// String 的 replaceAll方法
String content = "JDK1.3 JDK1.4 JDK1.3 JDK1.5";
//String newContent = content.replaceAll("JDK1[.](3|4)", "JDK");
String newContent = content.replaceAll("JDK1.3|JDK1.4", "JDK");
System.out.println("newContent = " + newContent);
}
@Test
public void test04() {
String content = "13539905434";
if (content.matches("1(35|78)\\d{8}"))
System.out.println("success");
else
System.out.println("falied");
}
@Test
public void test05() {
String content = "hello#abc-jack12smith~北京";
String[] split = content.split("#|-|\\d+|~");
for (String regStr : split) {
System.out.println("regStr = " + regStr);
}
}
神奇的网站 : https://www.r2coding.com/#/README