Java正则表达式详解

一、开山入门

案例一

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);

、、

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值