一、正则表达式快速入门
public class Regexp_ { public static void main(String[] args) { String conten = "2010年,Java编程语言的共同创始人之一詹姆斯·高斯林从Oracle公司辞职。2011年,甲骨文公司举行了全球性的活动,以庆祝Java7的推出,随后Java7正式发布。"; // 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(conten); // 3. 循环匹配,匹配成功返回 true while (matcher.find()) { System.out.println("找到:" + matcher.group(0)); } } }
正则表达式:Regular Expression【regex/RE】
二、正则表达式底层实现
public class RETheory01 { public static void main(String[] args) { String conten = "1998年12月8日,第二代Java平台的企业版J2EE发布。1999年6月,Sun公司发布了" + "第二代Java平台(简称为Java2)的3个版本:J2ME(Java2 Micro Edition,Java2平台的微型" + "版),应用于移动、无线及有限资源的环境;J2SE(Java 2 Standard Edition,Java 2平台的" + "标准版),应用于桌面环境;J2EE(Java 2Enterprise Edition,Java 2平台的企业版),应" + "用于基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个" + "里程碑,标志着Java的应用开始普及。"; // 目标:匹配所有4个数字 // 1. \\d 表示一个任意的数字 String regStr = "\\d\\d\\d\\d"; // 2. 创建模式对象【即正则表达式对象】 Pattern pattern = Pattern.compile(regStr); // 3. 创建匹配器 Matcher matcher = pattern.matcher(conten); /** * matcher.find() * 1.根据指定的规则,定位满足规则的子字符串(比如1998) * 2.找到后,将 子字符串的开始的索引记录到 matcher 对象的属性 int[] groups * groups[0]=0,把该子字符串的 结束的索引+1 的值记录到 groups[1]=4 * 3.同时记录 oldLast 的值为子字符串的 结束的索引+1 的值即4,即下次执行find时,就从4开始匹配 */ // 循环匹配 while (matcher.find()) { /** * 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开始截取子字符串返回 */ System.out.println("找到:" + matcher.group(0)); } } }
正则表达式中()表示为分组public class RETheory02 { public static void main(String[] args) { String conten = "1998年12月8日,第二代Java平台的企业版J2EE发布。1999年6月,Sun公司发布了" + "第二代Java平台(简称为Java2)的3个版本:J2ME(Java2 Micro Edition,Java2平台的微型" + "版),应用于移动、无线及有限资源的环境;J2SE(Java 2 Standard Edition,Java 2平台的" + "标准版),应用于桌面环境;J2EE(Java 2Enterprise Edition,Java 2平台的企业版),应" + "用于基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个" + "里程碑,标志着Java的应用开始普及。"; // 目标:匹配所有4个数字 // 1. \\d 表示一个任意的数字 // 正则表达式中()表示为分组 String regStr = "(\\d\\d)(\\d\\d)"; // 2. 创建模式对象【即正则表达式对象】 Pattern pattern = Pattern.compile(regStr); // 3. 创建匹配器 Matcher matcher = pattern.matcher(conten); /** * matcher.find() * 1.根据指定的规则,定位满足规则的子字符串(比如1998) * 2.找到后,将 子字符串的开始的索引记录到 matcher 对象的属性 int[] groups * 2.1 groups[0]=0,把该子字符串的 结束的索引+1 的值记录到 groups[1]=4 * 2.2 记录1组【19】:groups[2]=0 groups[3]=2 * 2.3 记录2组【98】:groups[4]=2 groups[5]=4 * 2.4 如果有更多的分组...... * 3.同时记录 oldLast 的值为子字符串的 结束的索引+1 的值即4,即下次执行find时,就从4开始匹配 */ // 循环匹配 while (matcher.find()) { /** * 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开始截取子字符串返回 * 2.根据 groups[2]=0 和 groups[3]=2 的记录的位置,从content开始截取子字符串返回 * 3.根据 groups[4]=2 和 groups[5]=4 的记录的位置,从content开始截取子字符串返回 */ System.out.println("找到:" + matcher.group(0)); System.out.println("第1组匹配的值:" + matcher.group(1)); System.out.println("第2组匹配的值:" + matcher.group(2)); }
三、正则表达式语法
1. 基本介绍
如果要想灵活的运用正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:
(1)限定符
(2)选择匹配符
(3)分组组合和反向引用符
(4)特殊字符
(5)字符匹配符
(6)定位符
2. 元字符 - 转义符【\\】
需要用到转义符号的字符有以下:【.】【*】【+】【(】【)】【$】【/】【\】【?】【[】【]】【^】【{】【}】
在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号,否则检索不到结果,甚至会报错的。
public class RegExp02 { public static void main(String[] args) { String content = "abc$(abc(123("; // String regStr = "("; // 错误 String regStr = "\\("; Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); while (matcher.find()){ System.out.println("找到:"+matcher.group(0)); } } }
提示:
在Java的正则表达式中,两个【\\】代表其他语言中的一个【\】
3. 元字符 - 字符匹配符
public class RegExp03 { public static void main(String[] args) { // java正则表达式默认是区分字母大小写的,如何实现不区分大小写 String content = "a11abc$ABC"; // String regStr = "(?i)abc"; // abc不区分大小写 // String regStr = "a(?i)bc"; // bc不区分大小写 String regStr = "a((?i)b)c"; // b不区分大小写 // 当创建 Pattern 对象时,指定 Pattern.CASE_INSENSITIVE,表示匹配是不区分字母大小写。 Pattern pattern = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(content); while (matcher.find()){ System.out.println("找到:"+matcher.group(0)); } } }
public class RegExp04 { public static void main(String[] args) { String content = "a11_ abc$ABC y"; // String regStr = "[^a-z]"; // String regStr = "[^a-z]{2}"; // String regStr = "[^0-9]"; // String regStr = "[ac]"; // String regStr = "\\D"; // String regStr = "\\w"; // String regStr = "\\s"; // \\s 匹配任何空白字符(空格、制表符) // String regStr = "\\S"; // \\S 匹配任何非空白字符 String regStr = "."; // 匹配除 \n 之外的所有字符 Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); while (matcher.find()){ System.out.println("找到:"+matcher.group(0)); } } }
4. 元字符 - 选择匹配符
在匹配某个字符串的时候是选择性的,即:既可以匹配这个,又可以匹配那个,这时你需
要用到选择匹配符号public class RegExp05 { public static void main(String[] args) { String content = "夏天 炎热 abc"; String regStr = "夏|炎|c"; Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); while (matcher.find()) { System.out.println("找到:" + matcher.group(0)); } } }
5. 元字符 - 限定符
用于指定其前面的字符和组合项连续出现多少次
public class RegExp06 { public static void main(String[] args) { String content = "a1111111aaaaaa451hi"; // String regStr = "a{3}"; // 表示匹配 aaa // String regStr = "1{4}"; // 表示匹配 1111 // String regStr = "\\d{2}"; // 表示匹配 两位的任意数字字符 // Java匹配默认贪婪匹配,即尽可能匹配多的,aaaa优先于aaa // String regStr = "a{3,4}"; // 表示匹配 aaa 或者 aaaa // String regStr = "1{4,5}"; // 表示匹配 1111 或者 11111 // String regStr = "\\d{2,5}"; // 表示匹配 两位数到五位数 // String regStr = "1+"; // 表示匹配 1个1或多个1 // String regStr = "\\d+"; // 表示匹配 1个数字或多个数字 // 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)); } } }
6. 元字符 - 定位符
定位符。规定要匹配的字符串出现的位置,比如在字符串的开始还是在结束的位置
public class RegExp07 { public static void main(String[] args) { String content = "123abc"; // String regStr = "^[0-9]+[a-z]*"; // 表示匹配 至少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)); } } }
7. 捕获分组
public class RegExp08 { @Test public void test1(){ String content = "abc1997zzz2022"; // 非命名分组 String regStr = "(\\d\\d)(\\d)(\\d)"; // 表示匹配 至少1个数字开头,并以至少1个小写字母的字符串 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个分组的内容 System.out.println("找到:" + matcher.group(2)); // 匹配的字符串的第2个分组的内容 System.out.println("找到:" + matcher.group(3)); // 匹配的字符串的第3个分组的内容 } } @Test public void test2(){ String content = "abc1997zzz2022"; // 命名分组,即可以给分组取名 String regStr = "(?<g1>\\d\\d)(?<yi2>\\d)(\\d)"; // 表示匹配 至少1个数字开头,并以至少1个小写字母的字符串 Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); while (matcher.find()) { System.out.println("找到:" + matcher.group(0)); // 匹配的字符串 System.out.println("找到:" + matcher.group("g1")); // 匹配的字符串的"g1"分组的内容 System.out.println("找到:" + matcher.group("yi2")); // 匹配的字符串的"yi2"分组的内容 System.out.println("找到:" + matcher.group(3)); // 匹配的字符串的第3个分组的内容 } } }
8. 非捕获分组
public class RegExp09 { /** * 找到韩顺平教育、韩顺平老师、韩顺平同学子字符串 */ @Test public void test1() { 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)); } } /** * 找到韩顺平这个关键字,但是要求只是查找韩顺平教育和韩顺平老师中包含有的韩顺平 */ @Test public void test2() { 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)); } } /** * 找到韩顺平这个关键字,但是要求只是查找不是(韩顺平教育和韩顺平老师)中包含有的韩顺平 */ @Test public void test3() { 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)); } } }
9. 非贪婪匹配
/** * 非贪婪匹配 */ public class RegExp10 { @Test public void test1() { String content = "hello111111 ok"; // String regStr = "\\d+"; // 默认是贪婪匹配 String regStr = "\\d+?"; // 非贪婪匹配 Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); while (matcher.find()) { System.out.println("找到:" + matcher.group(0)); } } }