Java拓展 - 正则表达式底层实现与案例讲解

为什么要学习正则表达式

提出问题1

(文本)

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平台的企业版),应用3443于基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个里程碑,标志着Java的应用开始普及9889

  1. 给你一个字符串(或文章),请你找出所有四个数字连在一起的子串?
  2. 给你一个字符串(或文章),请你找出所有四个数字连在一起的子串,并且这四个数字要满足:第一位与第四位相同,第二位与第三位相同,比如1221,5775

提出问题2

  1. 请验证输入的邮件,是否符合电子邮件格式
  2. 请验证输入的手机号,是否符合手机号格式

请添加图片描述

结论

  1. 正则表达式是对字符串执行模式匹配的技术
  2. 正则表达式专门用于处理类似文本问题
  3. 正则表达式:regular expression => RegExp

正则表达式基本介绍

基本介绍

  1. 一个正则表达式,就是用某种模式去匹配字符串的一个公式。很多人因为它们看上去比较古怪而且复杂所以不敢去使用,不过,经过练习后,就觉得这些复杂的表达式写起来还是相当简单的,而且,一旦你弄懂它们,你就能把数小时辛苦而且易错的文本处理工作缩短在几分钟(甚至几秒钟)内完成

  2. 正则表达式不是只有java才有,实际上很多编程语言都支持正则表达式进行字符串操作!

请添加图片描述

实例分析

为让大家对正则表达式底层实现有一个直观的映像,给大家举个实例

给你一段字符串(文本),请找出所有四个数字连在一起的子串,比如:应该找到 1998 1999 3443 9899 ===>分析底层实现

代码实现

package com.taotao.regexp;

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

/**
 * Create By 刘鸿涛
 * 2022/3/7 19:10
 * 分析java的正则表达式的底层实现
 */
@SuppressWarnings({"all"})
public class RegTheory {
    public static void main(String[] args) {
        String content = "1998年12月8日,第二代Java平台的企业版J2EE发布。1999年6月,Sun公司发布了第二代J" +
                "ava平台(简称为Java2)的3个版本:J2ME (Java2 Micro Edition,Java2平台的微型版),应用于移动、" +
                "无线及有限资源的环境;J2SE (Java 2 Standard Edition,Java 2平台的标准版),应用于桌面环境;J2EE (Java 2Enterprise Edition" +
                ",Java 2平台的企业版),应用3443于基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个里程碑,标志着Java的应用开始普及9889";

        //目标:匹配所有四个数字
        //1.\\d 表示一个任意的数字
        String regStr = "\\d\\d\\d\\d";
        //2.创建模式对象
        Pattern pattern = Pattern.compile(regStr);
        //3.创建匹配器
        //说明:创建匹配器matcher,按照 正则表达式的规则,去匹配 content字符串
        Matcher matcher = pattern.matcher(content);

        //4.开始匹配
        int n = 1;
        while(matcher.find()){
            System.out.println("找到第" + (n++) + "个" + matcher.group(0));
        }
    }
}

请添加图片描述

正则底层分析(group())

package com.taotao.regexp;

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

/**
 * Create By 刘鸿涛
 * 2022/3/7 19:10
 * 分析java的正则表达式的底层实现
 */
@SuppressWarnings({"all"})
public class RegTheory {
    public static void main(String[] args) {
        String content = "1998年12月8日,第二代Java平台的企业版J2EE发布。1999年6月,Sun公司发布了第二代J" +
                "ava平台(简称为Java2)的3个版本:J2ME (Java2 Micro Edition,Java2平台的微型版),应用于移动、" +
                "无线及有限资源的环境;J2SE (Java 2 Standard Edition,Java 2平台的标准版),应用于桌面环境;J2EE (Java 2Enterprise Edition" +
                ",Java 2平台的企业版),应用3443于基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个里程碑,标志着Java的应用开始普及9889";

        //目标:匹配所有四个数字
        //1.\\d 表示一个任意的数字
        String regStr = "\\d\\d\\d\\d";
        //2.创建模式对象
        Pattern pattern = Pattern.compile(regStr);
        //3.创建匹配器
        //说明:创建匹配器matcher,按照 正则表达式的规则,去匹配 content字符串
        Matcher matcher = pattern.matcher(content);

        //4.开始匹配
        int n = 1;
        /**
         * matcher.find()完成的任务
         * 1.根据指定的规则,定位满足规则的子字符串(比如1998)
         * 2.找到后,将 子字符串的开始的索引记录到 matcher对象的属性 int【】 groups;
         *          gruops[0] = 0,把该子字符串的结束的索引 + 1的值记录到 groups[1] = 4;
         *          gruops[0] = 31,把该子字符串的结束的索引 + 1的值记录到 groups[1] = 35;
         *
         * 3.同时记录oldLast 的值为 子字符串的结束的 索引 +1 的值 即4,即下次执行find时,就从4开始匹配
         * 同时记录oldLast 的值为 子字符串的结束的 索引 +1 的值 即35,即下次执行find时,就从35开始匹配
         *
         *
         * 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的记录的位置,从contenet开始截取子字符串返回
         *          就是[0,4)
         *  1.根据 groups[0] = 31 和 groups[1] = 35 的记录的位置,从contenet开始截取子字符串返回
         *          就是[31,35)
         *  如果再执行find方法,仍然按
         */
        while(matcher.find()){
            System.out.println("找到第" + (n++) + "个" + matcher.group(0));
        }
    }
}

正则底层分析(分组)

请添加图片描述

代码

package com.taotao.regexp;

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

/**
 * Create By 刘鸿涛
 * 2022/3/7 19:10
 * 分析java的正则表达式的底层实现
 */
@SuppressWarnings({"all"})
public class RegTheory {
    public static void main(String[] args) {
        String content = "1998年12月8日,第二代Java平台的企业版J2EE发布。1999年6月,Sun公司发布了第二代J" +
                "ava平台(简称为Java2)的3个版本:J2ME (Java2 Micro Edition,Java2平台的微型版),应用于移动、" +
                "无线及有限资源的环境;J2SE (Java 2 Standard Edition,Java 2平台的标准版),应用于桌面环境;J2EE (Java 2Enterprise Edition" +
                ",Java 2平台的企业版),应用3443于基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个里程碑,标志着Java的应用开始普及9889";

        //目标:匹配所有四个数字
        //1.\\d 表示一个任意的数字
        String regStr = "(\\d\\d)(\\d\\d)";
        //2.创建模式对象
        Pattern pattern = Pattern.compile(regStr);
        //3.创建匹配器
        //说明:创建匹配器matcher,按照 正则表达式的规则,去匹配 content字符串
        Matcher matcher = pattern.matcher(content);

        //4.开始匹配
        /**
         * matcher.find()完成的任务 (考虑分组)
         * 什么是分组,比如 (\d\d)(\d\d),正则表达式中有()表示分组,第一个()表示第一组,第二个小括号表示第二组()
         * 1.根据指定的规则,定位满足规则的子字符串(比如(19)98)
         * 2.找到后,将 子字符串的开始的索引记录到 matcher对象的属性 int【】 groups;
         *          2.1 gruops[0] = 0,把该子字符串的结束的索引 + 1的值记录到 groups[1] = 4;
         *          2.2 记录第一组()匹配到的字符串 groups[2] = 0 groups[3] = 2
         *          2.3 记录2组()匹配到的字符串 groups[4] = 2 groups[5] = 4
         *          2.4 如果有更多的分组.....
         *
         * 3.同时记录oldLast 的值为 子字符串的结束的 索引 +1 的值 即4,即下次执行find时,就从4开始匹配
         * 同时记录oldLast 的值为 子字符串的结束的 索引 +1 的值 即35,即下次执行find时,就从35开始匹配
         *
         *
         * 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的记录的位置,从contenet开始截取子字符串返回
         *          就是[0,4)
         *  1.根据 groups[0] = 31 和 groups[1] = 35 的记录的位置,从contenet开始截取子字符串返回
         *          就是[31,35)
         *  如果再执行find方法,仍然按
         */
        while(matcher.find()){
            System.out.println("找到" + matcher.group(0));
            System.out.println("找到" + matcher.group(1));
            System.out.println("找到" + matcher.group(2));
        }
    }
}

输出结果

请添加图片描述

注意

如果此时取出group(3),那么就会索引越界,因为没有第三组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼鬼骑士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值