java基础18--正则表达式

正则表达式

正则表达式底层实现

package com.bj.regexp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 毕晶
 * @date 2022/7/29 4:47 PM
 * 分析java正则表达式底层实现
 */
public class RegTheory {

    public static void main(String[] args) {
        String content = "2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。2001年9月24日,J2EE1" +
                ".3发布。2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升,与J2SE1" +
                ".3相比,其多了近62%的类和接口。在这些新特性当中,还提供了广泛的XML支持、安全套接字(Socket)支持(通过SSL与TLS协议)、全新的I/OAPI、正则表达式、日志与断言。2004年9月30" +
                "日,J2SE1.5发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性,J2SE 1.5更名为Java SE 5.0(内部版本号1.5" +
                ".0),代号为“Tiger”,Tiger包含了从1996年发布1.0版本以来的最重大的更新,其中包括泛型支持、基本类型的自动装箱、改进的循环、枚举类型、格式化I/O及可变参数。";
        //目标:匹配所有四个数字
        //1.\\d 表示一个任意0-9的数字
//        String regStr = "\\d\\d\\d\\d";
        String regStr = "(\\d\\d)(\\d\\d)";//分组
        //2.创建模式对象
        Pattern pattern = Pattern.compile(regStr);
        //3.创建一个匹配器,按照regStr规则去匹配content字符串
        Matcher matcher = pattern.matcher(content);
        //4.开始匹配
        /*
         matcher.find()完成的任务
         1.根据指定的规则,定位满足条件的子字符串(如2000)
         2.找到后将子字符串开始的索引记录到matcher对象的属性中 int[] groups;
         groups[0] = 0,把该子字符串的结束的索引+1的值记录到groups[1] = 4(2000在文本中最后一个0的索引+1)

         分组时: // 如果分组的话,还会把第一组()匹配到的字符串(20)放入groups[2]=0中,groups[3] =2,{groups[]中放的是在 文本中的 索引索引索引!}
         //第二组匹配到的(00),groups[4]=2,groups[5]=4
         //....以此类推

         3.同时记录oldLast的值为子字符串结束的索引+1的值(4),下次执行find方法时从4开始匹配
         **/

        /*
         * matcher.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.如group=0,根据groups[0]=0和groups[1]=4记录的位置,从content开始截取子字符串返回,就是content中[0,4)的字符串
         *
         *  如果再次执行这个find()方法就从oldLast位置开始了,后面同理
         *
         * */

        /*
         *         String regStr = "(\\d\\d)(\\d\\d)";//分组
         *      什么是分组?
         *      正则中带()就是分组,第一个()表示第一组,第二个()表示第二组...
         *
         *      为什么是groups[group * 2], groups[group * 2 + 1]?
         *      因为groups中每次用两个长度存放开始和结束的字符串索引,索引传入group(value)方法中的value在经过
         *      group*2和group*2+1后刚好是groups中进行分组后的开始下标和结束下标
         *
         *      补充:String有个subSequence()方法,该方法的底层是subString(a,b)--[a,b)
         *
         * */

        /**
         * 小结:
         *1.如果正则表达式有分组(),
         *2.取出的字符串规则如下:
         *3.matcher.group(0) 返回匹配pattern的字符串
         *4.matcher.group(1) 返回分组第一组字符串,group方法会自动在groups中取groups[2],groups[3]
         *5.matcher.group(2) 返回分组第一组字符串
         *6. ...,但是不能越界
         *
         * */
        while (matcher.find()) {
            System.out.println("找到: " + matcher.group(0));
            System.out.println("第一组():" + matcher.group(1));
            System.out.println("第二组():" + matcher.group(2));
        }
    }

}

在这里插入图片描述

正则表达式语法

基本介绍

在这里插入图片描述

转义号

在这里插入图片描述
在这里插入图片描述

字符匹配符

在这里插入图片描述
在这里插入图片描述

字符匹配符应用案例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

选择匹配符

在这里插入图片描述

限定符

注意:指定的对象是前面的字符和组合项(就是括号括起来的)
在这里插入图片描述
在这里插入图片描述
细节:java匹配时贪婪匹配,尽可能匹配多的
如:
content=“aaaaaa”
a{3,4},匹配3个或者4个a,
匹配结果是aaaa,而不是aaa aaa

定位符

注意:

  1. ^只有在 [ ^ ]里面才表示非,在外面表示开头
  2. ^要写在前面
  3. $要写在后面
  4. han\b可以理解为右边界有han或者说以han结尾,被空格分隔的也算
  5. han\B可以理解为左边界有han或者说以han开头,被空格分隔的也算
    在这里插入图片描述

分组(捕获分组)

注意:捕获指的是可以通过group(1)…来得到想要的分组中的内容
在这里插入图片描述

特别分组(非捕获分组)

在这里插入图片描述

package com.bj.regexp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 毕晶
 * @date 2022/8/1 3:33 PM
 * 演示非捕获分组
 */
public class RegExp08 {
    public static void main(String[] args) {

        String content = "hello韩顺平教育 jack韩顺平老师 韩顺平同学hello";
        /*
         * 1.找到 韩顺平教育 韩顺平老师 韩顺平同学 子字符串
         * 2.找到韩顺平关键字,要求只查找韩顺平教育和韩顺平老师中包含的的韩顺平
         * 3.找到韩顺平关键字,但是要求不是(韩顺平教育和韩顺平老师)中包含的韩顺平
         * */
        String regStr1 = "韩顺平(?:教育|老师|同学)";//等价"韩顺平教育|韩顺平老师|韩顺平同学"
        String regStr2 = "韩顺平(?=教育|老师)";
        String regStr3 = "韩顺平(?!教育|老师)";
        Pattern pattern = Pattern.compile(regStr3);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

非贪婪匹配

想要非贪婪就在非限定符后面加个?
在这里插入图片描述

package com.bj.regexp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 毕晶
 * @date 2022/8/1 3:58 PM
 * 演示非贪婪匹配
 */
public class RegExp09 {
    public static void main(String[] args) {
        String content = "hello11111 ok";
        String regStr1 = "\\d+";//匹配1-n个数字,默认找n个数字,贪婪匹配
        String regStr2 = "\\d+?";//匹配1-n个数字,默认找1一个数字,非贪婪匹配,限定符后面加问号
        Pattern pattern = Pattern.compile(regStr1);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

应用实例

注意:[?.]表示匹配的就是?或者.本身

package com.bj.regexp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 毕晶
 * @date 2022/8/1 4:05 PM
 * 实例
 */
public class RegExp10 {
    public static void main(String[] args) {
        /*
         * 1.汉字 regStr1 = "^[\u0391-\uffe5]+$"
         * 2.邮政编码:1-9开头的六位数 regStr2 = "^[1-9][0-9]{5}"
         * 3.qq号码:1-9开头的5-10位数
         * 4.手机号码:13,14,15,18开头的11位数
         * 5.url
         * */

        String content1 = "韩顺平教育";
        String content2 = "100000";
        String regStr1 = "^[\u0391-\uffe5]+$";
        String regStr2 = "^[1-9][0-9]{5}";
        String regStr3 = "^[1-9]\\d{4,9}";
        String regStr4 = "^1(?:3|4|5|8)\\d{9}";

        String content5 = "https://www.bilibili.com";
        //[?.]表示匹配的就是?或者.本身
        String regStr5 = "^(https?://)([\\w-]+\\.)+[\\w-]+(\\/[\\w=-?&/%.#]*)?$";//(https://)(www.bilibili.)(com)(......)
        Pattern pattern = Pattern.compile(regStr5);
        Matcher matcher = pattern.matcher(content5);
        System.out.println(matcher.find() ? "满足" : "不满足");
    }
}

正则表达式的三个常用类

在这里插入图片描述

Pattern类

Pattern的matches方法

在这里插入图片描述

Pattern的matches方法里面封装的是Matcher的matches方法

package com.bj.regexp.pattern;

import java.util.regex.Pattern;

/**
 * @author 毕晶
 * @date 2022/8/1 6:47 PM
 * 演示match方法,用于整体匹配,在验证输入的字符串是否满足条件时使用
 */
public class PatternMethod {
    public static void main(String[] args) {
        String content = "hsp from hspedu";
        String regStr = ".*hsp.*";

        boolean matches = Pattern.matches(regStr, content);
        System.out.println("整体匹配=" + matches);//true
    }
}

Matcher类

在这里插入图片描述
在这里插入图片描述

反向引用

提出需求

在这里插入图片描述

几个概念

在这里插入图片描述

反向引用的案例

在这里插入图片描述

package com.bj.regexp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 毕晶
 * @date 2022/8/1 8:00 PM
 * 演示反向引用
 */
public class BackReference {
    public static void main(String[] args) {
//        String content = "hello 0990 jack2332 tom11 jack22 yyy xxx";
        String content = "12321-333999111";
        /*
         * 1.匹配两个连续相同的数字(\\d)\\1
         * 2.匹配5个连续相同的数字(\\d)\\1{4}
         * 3.匹配个位和千位相同,十位和百位相同的数,如5221,1551 (\\d)(\\d)\\2\\1
         * */

        /**
         * 请在字符串中检索商品编号,形式如12321-333999111这种号码
         * 要求满足前面的是一个五位数,然后一个-号,然后一个九位数,连续的三位要相同
         * */
        String regStr = "(\\d)\\1";
        String regStr2 = "(\\w)\\1";
        String regStr3 = "(\\d)(\\d)\\2\\1";
        String regStr4 = "\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}";
        Pattern pattern = Pattern.compile(regStr4);
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
    }
}

结巴去重案例

在这里插入图片描述

package com.bj.regexp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 毕晶
 * @date 2022/8/1 8:19 PM
 * 演示结巴去重
 */
public class Distinct {

    public static void main(String[] args) {
        String content = "我....我要....学学学....编程java!";
        //1.去掉.
        Pattern pattern = Pattern.compile("\\.");
        Matcher matcher = pattern.matcher(content);
        String newString = matcher.replaceAll("");
        //2.去掉重复字符
        //(1)找到重复的字符(.)\\1
        pattern = Pattern.compile("(.)\\1+");
        matcher = pattern.matcher(newString);
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }
        //(2)外部反向引用($1),就是刚刚内部引用时找到的会重复的单个字符
        content = matcher.replaceAll("$1");
        System.out.println(content);
    }

}

String类中使用正则表达式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.bj.regexp;

/**
 * @author 毕晶
 * @date 2022/8/2 2:15 PM
 * 演示String类中的正则
 */
public class StringReg {
    public static void main(String[] args) {
        String content = "jdk1.7 and jdk1.8";
        System.out.println(content.replaceAll("jdk1\\.(?:7|8)", "jdk"));
        String content2 = "13854598721";
        System.out.println(content2.matches("^13(?:8|9)\\d{8}"));
        String content3 = "hello#abc-jack12smith~北京";
        String[] strings = content3.split("#|-|~|\\d+");
        for (String string : strings) {
            System.out.println(string);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值