“正则表达式 底层实现”的版本间的差异

来自姬鸿昌的知识库
跳到导航 跳到搜索
 
(未显示同一用户的3个中间版本)
第1行: 第1行:
 
https://www.bilibili.com/video/BV1Eq4y1E79W/?p=3
 
https://www.bilibili.com/video/BV1Eq4y1E79W/?p=3
  
=== 找出所有四个数字连在一起的子串 ===
+
=== 示例:找出所有四个数字连在一起的子串 ===
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
import java.util.regex.Matcher;
 
import java.util.regex.Matcher;
第91行: 第91行:
  
 
=== matcher.group(0)、matcher.group(1)……分组的概念 ===
 
=== matcher.group(0)、matcher.group(1)……分组的概念 ===
 +
<syntaxhighlight lang="java">
 +
import java.util.regex.Matcher;
 +
import java.util.regex.Pattern;
 +
 +
public class RegTheory1 {
 +
 +
    public static void main(String[] args) {
 +
 +
        String content = "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、\\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个()表示第1组,第2个()表示第2组,……
 +
        * 1、根据指定的规则,定位满足规则的子字符串(比如:(19)(98))
 +
        * 2、找到后,将子字符串的开始下标记录到 matcher 对象的属性 int[] groups;
 +
        *  2.1、groups[0] = 0,把该子字符串的结束下标+1的值记录到 groups[1] = 4;
 +
        *  2.2、记录1组()匹配到的字符串 groups[2] = 0 groups[3] = 2
 +
        *  2.3、记录2组()匹配到的字符串 groups[4] = 2 groups[5] = 4
 +
        *  2.4、如果有更多的分组……
 +
        * 3、同时记录 oldLast 的值为子字符串的结束下标+1的值,下次执行 matcher.find()时,就从 oldLast 开始匹配
 +
        */
 +
        while (matcher.find()) {
 +
            System.out.println("找到:" + matcher.group(0));
 +
            System.out.println("找到1组:" + matcher.group(1));
 +
            System.out.println("找到2组:" + matcher.group(2));
 +
            System.out.println();
 +
        }
 +
    }
 +
 +
}
 +
</syntaxhighlight><syntaxhighlight lang="console">
 +
找到:1998
 +
找到1组:19
 +
找到2组:98
 +
 +
找到:1999
 +
找到1组:19
 +
找到2组:99
 +
 +
找到:3443
 +
找到1组:34
 +
找到2组:43
 +
 +
找到:9889
 +
找到1组:98
 +
找到2组:89
 +
</syntaxhighlight>
 +
[[文件:正则表达式 底层实现 调试.png|无|缩略图|682x682像素]]
 +
 +
==== 小结 ====
 +
1、如果正则表达式有() 即分组
 +
 +
2、取出匹配的字符串规则如下:
 +
 +
group(0) 表示匹配到的子字符串
 +
 +
group(1) 表示匹配到的子字符串的第1组子串
 +
 +
group(2) 表示匹配到的子字符串的第2组子串
 +
 +
……
 +
 +
但是分组的数不能越界

2022年11月15日 (二) 05:51的最新版本

https://www.bilibili.com/video/BV1Eq4y1E79W/?p=3

示例:找出所有四个数字连在一起的子串

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

public class RegTheory {

    public static void main(String[] args) {

        String content = "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、\\d 表示一个任意的数字
         */
        String regStr = "\\d\\d\\d\\d";

        //2、创建模式对象
        Pattern pattern = Pattern.compile(regStr);

        /**
         * 3、创建匹配器
         * 说明:创建匹配器 matcher,按照正则表达式的规则,取匹配 content 字符串
         */
        Matcher matcher = pattern.matcher(content);

        //4、开始匹配
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }

    }

}
找到:1998
找到:1999
找到:3443
找到:9889



https://www.bilibili.com/video/BV1Eq4y1E79W/?p=4

matcher.find() 完成的任务

        /**
         * matcher.find() 完成的任务
         * 1、根据指定的规则,定位满足规则的子字符串(比如:1998)
         * 2、找到后,将子字符串的开始下标记录到 matcher 对象的属性 int[] groups;
         *    groups[0]=0,把该子字符串的结束下标+1的值记录到 group[1] = 4
         * 3、同时记录 oldLast 的值为子字符串的下标+1的值即4,即下次执行matcher.find()时,就从4开始匹配
         *
         * 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 的记录的位置,从 content 开始截取子字符串返回
         *    就是[0,4) 包含0 但是不包含下标为4的位置
         *
         * 如果再次指向 find 方法,仍然按上面分析来执行
         */
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
        }

断点调试,观察、验证整个过程



https://www.bilibili.com/video/BV1Eq4y1E79W/?p=5

matcher.group(0)、matcher.group(1)……分组的概念

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

public class RegTheory1 {

    public static void main(String[] args) {

        String content = "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、\\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个()表示第1组,第2个()表示第2组,……
         * 1、根据指定的规则,定位满足规则的子字符串(比如:(19)(98))
         * 2、找到后,将子字符串的开始下标记录到 matcher 对象的属性 int[] groups;
         *   2.1、groups[0] = 0,把该子字符串的结束下标+1的值记录到 groups[1] = 4;
         *   2.2、记录1组()匹配到的字符串 groups[2] = 0 groups[3] = 2
         *   2.3、记录2组()匹配到的字符串 groups[4] = 2 groups[5] = 4
         *   2.4、如果有更多的分组……
         * 3、同时记录 oldLast 的值为子字符串的结束下标+1的值,下次执行 matcher.find()时,就从 oldLast 开始匹配
         */
        while (matcher.find()) {
            System.out.println("找到:" + matcher.group(0));
            System.out.println("找到1组:" + matcher.group(1));
            System.out.println("找到2组:" + matcher.group(2));
            System.out.println();
        }
    }

}
找到:1998
找到1组:19
找到2组:98

找到:1999
找到1组:19
找到2组:99

找到:3443
找到1组:34
找到2组:43

找到:9889
找到1组:98
找到2组:89
生成缩略图出错:无法将缩略图保存到目标地点

小结

1、如果正则表达式有() 即分组

2、取出匹配的字符串规则如下:

group(0) 表示匹配到的子字符串

group(1) 表示匹配到的子字符串的第1组子串

group(2) 表示匹配到的子字符串的第2组子串

……

但是分组的数不能越界