正则表达式底层实现
package regexp01;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Mustang
* @create 2022-05-24 9:08
* <p>
* 分析java正则表达式的底层实现
*/
public class RegExp01 {
public static void main(String[] args) {
String content = "1998年12月8日,第二代Java平台的企业版J2EE发布。1999年6月,"+
"Sun公司发布了第二代Java平台(简称为Java2)的3个版本:J2ME(Java2 Micro Edition,"+
"Java2平台的微型版),应用于移动、无线及有限资源的环境;J2SE(Java2 Standard Edition,"+
"Java2平台的标准版),应用于桌面环境;J2EE(Java2 Enterprise Edition,Java2平台的企业版),"+
"应用3443于基于Java的应用服务器。Java2平台的发布,是Java发展过程中最重要的一个里程碑,"+
"标志着Java的应用开始普及9889";
//匹配所有4个数字
//1. \\d表示任意一个数字
//String regStr = "\\d\\d\\d\\d";
String regStr = "(\\d\\d)(\\d\\d)"; //分组
//2. 创建模式对象[即正则表达式对象]
Pattern pattern = Pattern.compile(regStr);
//3. 创建匹配器matcher,按照正则表达式规则pattern去匹配content字符串。
Matcher matcher = pattern.matcher(content);
//4. 开始匹配
/*
matcher.find()完成的任务:
1.根据指定的规则,定位满足规则的子字符串(比如1998)
2.找到后,将子字符串的开始的索引记录到matcher.对象的属性 int[] groups:
groups[0]=0,把该子字符串的结束的索引+1的值记录到groups[1]=4
3.同时记录oldLast的值为子字符串的结束的索引+1的值即4,即下次执行find时,就从4开始匹配。
考虑分组的情况:
什么是分组,比如(\d\d)(\d\d),正则表达式中有"()"表示分组,第1个()表示第1组,第2个()表示第2组.....
1.根据指定的规则,定位满足规则的子字符串(比如(19)(98))
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的位置.
2.如果再次指向find方法。仍然按照上面分析来执行。会覆盖上一次的groups[0]和groups[1]的值,再去执行matcher.group(0)取出的就是第二次匹配到的字符串
*/
while (matcher.find()) {
//1小结
//1.如果正则表达式有(),即分组
//2.取出匹配的字符串规则如下:
//3.group(0)表示匹配到的子字符串
//4.group(1)表示匹配到的子字串的第1组子串
//5.group(2)表示匹配到的子字符串的第2组子串
//6....,但是分组的数不能越界
System.out.println("找到:" + matcher.group(0));
/*
group方法:getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
第一组:groups[1*2]=groups[2]=0,groups[1*2+1]=groups[3]=2,即第一组从匹配到的子字符串索引[0,2),就是19;
第二组:groups[2*2]=groups[4]=2,groups[2*2+1]=groups[5]=4,即第一组从匹配到的子字符串索引[2,4),就是98;
*/
System.out.println("第一组()匹配到的值=" + matcher.group(1));
System.out.println("第二组()匹配到的值=" + matcher.group(2));
//System.out.println("第三组()匹配到的值=" + matcher.group(3)); //多取则索引越界
}
}
}
元字符
完整版看:正则表达式元字符
/*
如果要想灵活的运用正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:
1. 限定符
2. 选择匹配符
3. 分组组合和反向引用符
4. 特殊字符
5. 字符匹配符
6. 定位符
*/
字符匹配符
package regexp01;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Mustang
* @create 2022-05-24 10:07
* <p>
* 元字符-->字符匹配符
*/
public class RegExp02 {
public static void main(String[] args) {
//1.元字符-->转义字符
//java中转义字符 \\,其它语言是\
String content = "1bc(klj(&dk(";
String regExp = "\\(";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
System.out.print("(转义字符)找到:");
while (matcher.find()) {
System.out.print(matcher.group(0) + " ");
}
//结果:(转义字符)找到:( ( (
System.out.println();
//2.元字符-->字符匹配符 [] [^] - . \\d \\D等等
String content1 = "a11c8abcABC";
String regExp1 = "[a-z]"; //匹配a-z之间的任意一个字符
//结果:a c a b c
String regExp1 = "[A-Z]";
//结果:A B C
String regExp1 = "abc"; //匹配 abc字符串[默认区分大小写]
//结果:abc
String regExp1 = "(?i)abc"; //表示abc[不区分大小写 (?i) ]
//结果:abc ABC
String regExp1 = "a(?i)bc"; //表示bc不区分大小写
//结果:abc
String regExp1 = "a((?i)b)c"; //表示b不区分大小写
//结果:abc
Pattern pattern1 = Pattern.compile(regExp1,Pattern.CASE_INSENSITIVE);//CASE_INSENSITIVE不区分大小写
//结果:abc ABC
String regExp1 = "[^a-z]"; //匹配不在 a-z之间的任意一个字符
//结果:1 1 8 A B C
String regExp1 = "[abcd]"; //匹配 abcd中的任意一个字符
//结果:a c a b c
String regExp1 = "\\D"; //匹配 不在 0-9中的任意一个字符,相当于[^0-9]
//结果:a c a b c A B C
String content1 = "a11c8_abcABC@";
String regExp1 = "\\w"; //匹配 字母,数字,下划线中的任意一个字符
//结果:a 1 1 c 8 _ a b c A B C
String regExp1 = "\\W"; //相当于[^a-zA-z0-9_]
//结果:@
String content1 = "a11c8_a bcABC@";
String regExp1 = "\\s"; //匹配任何空白字符(空格,tab制表符等)。输出看不见显示结果,但是可以看见输出打印信息,由此证明匹配到了
//结果:(字符匹配符)找到:
String regExp1 = "\\S"; //匹配非空白字符(空格,tab制表符等)。和\\s相反
//结果:a 1 1 c 8 _ a b c A B C @
String content1 = "a11.c8_a bc\nABC@";
String regExp1 = "."; //.匹配除\n之外的所有字符,若要匹配.本身则使用转义字符\\.
//结果:a 1 1 . c 8 _ a b c A B C @
Pattern pattern1 = Pattern.compile(regExp1);
Matcher matcher1 = pattern1.matcher(content1);
System.out.print("(字符匹配符)找到:");
while (matcher1.find()) {
System.out.print(matcher1.group(0) + " ");
}
}
}
选择匹配符
package regexp01;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Mustang
* @create 2022-05-24 18:30
* <p>
* 元字符-->选择匹配符 |
*/
public class RegExp03 {
public static void main(String[] args) {
String content = "hanshunping 韩 寒冷";
String regExp = "han|韩|寒";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(content);
while (matcher.