• 解析正则表达式的底层实现原理


    解析正则表达式的底层实现原理

    1 原理

    根据捕获分组的数量确定Matcher类中的groups数组的下标最大位数,其计算公式如下所示

    下标最大位数=1+捕获分组数量*2;

    例如没有捕获分组,那么groups[0]和groups[1]是可用的,group[0]为符合模板字符串的子串的开始位置,groups[1]为符合模板字符串的子串的结束位置+1;其余位置均为默认值-1

    若有一个捕获分组时,那么groups[0]和groups[1]是可用的,group[0]为符合模板字符串的子串的开始位置,groups[1]为符合模板字符串的子串的结束位置+1;groups[2]为在之前找到的子串中查找符合捕获分组格式的子串,并把其开始位置(相对于原来字符串的位置)放入groups[2];结束位置的后一位放入groups[3]的位置的,并用oldlast记录group[1]的下标,下次从此位置开始往后找

    想获取第n个捕获分组的内容,就group[n]即可,通过n去截取符合全匹配结果的子串中的符合捕获分组条件的子串(位置是相对于原来字符串的位置)

    2 举例分析

    2.1 题目内容

    例如存在需要查找的字符串content="1924u1765nkf8976",模板字符串regex="(\\d\\d)\\d{2}"group(0)group(1)的值
    
    • 1
    • 2

    2.2 分析过程

    2.2.1 我们知道模板字符串regex有一个捕获分组,因此创建的matcher对象中的groups中可以获取字符串的坐标的最大下标为3,即除了groups[0],groups[1],groups[2],groups[3]可以设置下标外其他位置里面存放的值是都不行,且里面的值为-1,意味着group[2]会提示下标越界

    a 下标越界错误示例代码
    package Work;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    public class Test05 {
        public static void main(String[] args) {
           check("1924u1765nkf8976","(\\d\\d)\\d{2}");
        }
        public static void check(String content,String regex){
            Pattern pattern=Pattern.compile(regex);
            Matcher matcher = pattern.matcher(content);
            while(matcher.find()){
                System.out.println("全匹配子串为: "+matcher.group(0));
                System.out.println("在全匹配子串中符合捕获分组的子串为: "+matcher.group(1));
                //捕获分组有几个,你可以取的group(里面的值)就为几,超出就会报数组下标越界
                System.out.println(matcher.group(2));
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    b 下标越界错误示例截图

    在这里插入图片描述

    2.2.2 当matcher.find()第一次为true时,符合全匹配的字符串为"1924",此时groups[0]=0;groups[1]=3+1=4;符合捕获分组匹配的字符串为:“19”,此时groups[1]=0,groups[2]=1+1=2;

    在这里插入图片描述

    记录下次开始查找的位置
    在这里插入图片描述

    2.2.3 当matcher.find()第二次为true时,符合全匹配的字符串为"1765",此时groups[0]=5;groups[1]=8+1=9;符合捕获分组匹配的字符串为:“17”,此时groups[1]=5,groups[2]=6+1=7;

    在这里插入图片描述

    记录下次开始查找的位置
    在这里插入图片描述

    2.2.4 当matcher.find()第三次为true时,符合全匹配的字符串为"8976",此groups[0]=12;groups[1]=15+1=16;符合捕获分组匹配的字符串为:“89”,此时groups[1]=12,groups[2]=13+1=14;

    在这里插入图片描述

    记录下次开始查找的位置
    在这里插入图片描述

    2.2.5 当matcher.fine()循环第四次的时候发现没有符合模板字符串的子串了,那么就会结束循环,且matcher对象中的groups数组里面的所有值都会改为默认值-1,方便去进行下一次调用

    在这里插入图片描述

    3.示例代码

    package Work;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    public class Test05 {
        public static void main(String[] args) {
           check("1924u1765nkf8976","(\\d\\d)\\d{2}");
        }
        public static void check(String content,String regex){
            Pattern pattern=Pattern.compile(regex);
            Matcher matcher = pattern.matcher(content);
            while(matcher.find()){
                System.out.println("全匹配子串为: "+matcher.group(0));
                System.out.println("在全匹配子串中符合捕获分组的子串为: "+matcher.group(1));
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    4.示例代码运行截图

    在这里插入图片描述

  • 相关阅读:
    学习笔记-.net安全越权
    C: is too small to hold all values of ‘enum ABC‘
    CS110L(Rust)
    java.lang.OutOfMemoryError: Java heap space
    TIA博途Wincc Advanced下载项目的具体方法演示(V16版本)
    OpenCV 11(图像金字塔)
    Svelte-Ui-Admin基于svelte-ui中后台管理系统|Svelte3+Vite3后台框架
    LeetCode 第8题:字符串转换整数(Python3解法)
    HTML+CSS个人电影网页设计——电影从你的全世界路过(4页)带音乐特效
    Linux 指令学习
  • 原文地址:https://blog.csdn.net/SSS4362/article/details/126087215