一、开山入门
案例一
public static void main(String[] args) { String str="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的应用开始普及。"; //创建Pattern,模式对象 //1、\\d表示一个任意的数字 Pattern pattern=Pattern.compile("\\d\\d\\d\\d"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); } }
1、match.find()匹配原理
(1)根据指定的规则,定位满足规则的子字符串(比如1998)
(2)找到子字符串后,将子字符串的开始索引记录到matcher对象的属性int[] groups
groups[0]=0(1998中的1在str字符串中的字符索引为0),把子字符串的结束的索引+1的值记录在groups[1]=4(1998中的8在str字符串中的字符索引为3)
(3)同时记录oldLast的值为子字符串结束的索引+1的值(即4),当下次执行find方法时,就从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(); }
(1)根据groups[0]和groups[1]的记录的位置,从str开始截取子字符串[0,4)返回,此时返回1998
案例二
public static void main(String[] args) { String str="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的应用开始普及。"; //创建Pattern,模式对象 //1、\\d表示一个任意的数字 Pattern pattern=Pattern.compile("(\\d\\d)(\\d\\d)"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); System.out.println(matcher.group(1)); System.out.println(matcher.group(2)); } }
1、match.find()匹配原理
(\\d\\d)(\\d\\d),正则表达式中有(),表示分组,第一个()表示第一组,第二个()表示第二组
(1)根据指定的规则,定位满足规则的子字符串(比如1998)
(2)找到子字符串后,将子字符串的开始索引记录到matcher对象的属性int[] groups
1)groups[0]=0,子字符串的结束索引+1记录到groups[1]=4
2)记录第一组匹配到的字符串19,groups[2]=0(19的1在str中的索引为0),groups[3]=2(19中的9在str中的索引为1,记录的时候按照结尾索引+1)
3)记录第二组匹配的字符串98,groups[4]=2,groups[5]=4
matcher.group(1)和matcher.group(12)原理参照案例一中 matcher.group(0)的逻辑
二、正则表达式语法
1、转义符
遇到如下符号,需要转义
. * + () $ / \ ? [] ^ {}
2、字符匹配符
3、 选择匹配符
匹配某个字符的时候是选择性的,即可以匹配这个,又可以匹配那个。
4、限定符
指定其前面的字符和组合项连续出现多少次
5、定位符
指定要匹配的字符串出现的位置
6、分组
(1)捕获分组
Pattern pattern=Pattern.compile("(?<g1>\\d\\d)(\\d\\d)"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); System.out.println(matcher.group("g1")); System.out.println(matcher.group(2)); }
(2)非捕获分组
String str="hello java,hello jetty,hello netty"; //创建Pattern,模式对象 //匹配jetty或者netty Pattern pattern=Pattern.compile("(?:j|n)etty"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
String str="hello java,hello jetty,hello netty"; //创建Pattern,模式对象 //匹配hello netty,hello jetty的hello Pattern pattern=Pattern.compile("hello (?=netty|jetty)"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
String str="hello java,hello jetty,hello netty"; //创建Pattern,模式对象 //匹配不是hello java,hello jetty的hello Pattern pattern=Pattern.compile("hello (?!java|jetty)"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
7、反向引用
圆括号的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,此时称为反向引用。
(1)内部反向引用\\分组号
(2)外部反向引用$分组号
案例
(1)匹配两个连续的相同数字
String str="22"; Pattern pattern=Pattern.compile("(\\d)\\1"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
(2)匹配五个连续的相同数字
String str="22222"; Pattern pattern=Pattern.compile("(\\d){4}\\1"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
(3)匹配个位和千位相同,十位与百位相同的数
String str="5225"; Pattern pattern=Pattern.compile("(\\d)(\\d)\\2\\1"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
三、正则表达式的应用实例
1、提取汉字
String str="hello java,hello jetty,hello netty,你好"; //创建Pattern,模式对象 Pattern pattern=Pattern.compile("[\u0391-\uffe5]+$"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
2、校验URL地址
String str="https://www.baidu.com/s?wd=java&rsv_spt=1&rsv_iqid=0xca8e72ad0001b24b&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&rsv_sug3=5&rsv_sug1=4&rsv_sug7=101&rsv_sug2=0&rsv_btype=i&prefixsug=java&rsp=4&inputT=788&rsv_sug4=1500"; //创建Pattern,模式对象 //1、匹配协议头部:https:// http:// => ^((http|https)://) //2、匹配域名: www.baidu.com => ([\\w-]+\.)+[\\w-]+ //3、匹配剩余的内容 (\\/[\\w-+&#%=._]*)? //注意:[.]表示匹配"." Pattern pattern=Pattern.compile("^((http|https)://)([\\w-]+\\.)+[\\w-]+(\\/[\\w-+&#%=._?]*)?"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
3、匹配商品编号
String str="12321-333999111"; //商品编号:前面是一个5位数字,然后是一个-,然后是一个九位数,连续的每三位要相同 Pattern pattern=Pattern.compile("\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}"); //创建匹配器matcher,按照正则表达式的规则pattern,去匹配str Matcher matcher = pattern.matcher(str); //循环匹配 while (matcher.find()){ System.out.println(matcher.group(0)); }
4、结巴去重
//将 我....我要...学学学学....编程java 格式化为 我要学编程java String str="我....我要...学学学学....编程java"; //匹配所有点 Pattern pattern=Pattern.compile("\\."); Matcher matcher = pattern.matcher(str); //将所有“.”替换为空字符串 //content:我我要学学学学编程java String content = matcher.replaceAll(""); //使用内部反向引用匹配 (我我,学学学学) //分组的捕获内容(.)会被记录为$1 pattern = Pattern.compile("(.)\\1+"); matcher=pattern.matcher(content); //使用外部反向引用替换重复的,使用$1替换所有重复的 //result:我要学编程java String result = matcher.replaceAll("$1"); System.out.println(result);
、、