正则表达式的介绍与底层分析

正则表达式介绍

又称规则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sedgrep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。

正则表达式简单使用

假设你使用爬虫在网站上爬到此内容,该如何快速的获取到这段内容中的英文字母或者是数字?这个时候就用到了正则表达式

Python由荷兰数学计算机科学研究学会的吉多·范罗苏姆 于1990 年代初设计,作为一门叫做ABC语言的替代品。 [1] Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言, [2] 随着版本的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目的开发。 [3] Python解释器易于扩展,可以使用C语言C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。 [4] Python 也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码机器码。 [4] 2021年10月,语言流行指数的编译器Tiobe将Python加冕为最受欢迎的编程语言,20年来首次将其置于Java、C和JavaScript之上。

package regularexpression;

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

public class RegularExpression {
    public static void main(String[] args) {

        //假定使用爬虫爬取到了此内容
        String context = "Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆 于1990 年代初设计," +
                "作为一门叫做ABC语言的替代品。 [1]  Python提供了高效的高级数据结构,还能简单有效地面" +
                "向对象编程。Python语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速" +
                "开发应用的编程语言, [2]  随着版本的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目" +
                "的开发。 [3] "+"Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)" +
                "扩展新的功能和数据类" +
                "型。 [4]  Python 也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于" +
                "个主要系统平台的源码或机器码。 [4] " +
                "2021年10月,语言流行指数的编译器Tiobe将Python加冕为最受欢迎的编程语言,20年来首次将其置" +
                "于Java、C和JavaScript之上。 [16] ";
        //提取文章中所有的英文单词
        //先创建一个Pattern对象
        Pattern pattern = Pattern.compile("[a-zA-Z]+");
        //创建一个匹配对象
        //就是matcher 匹配器按照pattern模式理赔,到context文本中去匹配
        //找到就返回true 没有找到就返回false
        Matcher matcher = pattern.matcher(context);
        //开始匹配
        while (matcher.find()){
            //匹配到的内容会在matcher.group(0)中
            System.out.println("找到 " + matcher.group(0));
        }


    }
}

运行结果为

请添加图片描述

当我们需要获取文本中的数字时,只需要把这个语句

Pattern pattern = Pattern.compile("[a-zA-Z]+"); 

替换为

Pattern pattern = Pattern.compile("[0-9]+");

运行结果为

请添加图片描述

如果要抓取年份相关的则将

Pattern pattern = Pattern.compile("[0-9]+");

替换为

\ \d表示任意的数字

Pattern pattern = Pattern.compile(""\\d\\d\\d\\d"");

运行结果为

请添加图片描述

分析

martch.find()完成的任务

  1. 根据规则,定位到满足规则的子字符串
  2. 找到后,将紫子非常的开始的索引记录到 matcher对象属性 int[] groupsgroups[0] = 31 ,把该字字符串的借宿的索引+1的值记录到 groups[1] = 35

在此进行断点调试,发现确实有一个groups

请添加图片描述

当我们在往前走一步时候发现groups数组中 groups[0] = 31 groups[1] = 35

正好是1990在文本中的索引位置。

请添加图片描述

  1. 同时会记录oldLast的值,为子字符串结束的索引+1 的值即为35 ,即下次执行find时候,就从35这个位置开始匹配。
    请添加图片描述

march.group(0) 分析

我们通过group的源码

public String group(int group) {
    if (this.first < 0) {
        throw new IllegalStateException("No match found");
    } else if (group >= 0 && group <= this.groupCount()) {
        return this.groups[group * 2] != -1 && this.groups[group * 2 + 1] != -1 ? this.getSubSequence(this.groups[group * 2], this.groups[group * 2 + 1]).toString() : null;
    } else {
        throw new IndexOutOfBoundsException("No group " + group);
    }
}
  1. 根据groups[0] = 31groups[1] = 35记录的位置,从content开始截取字符串放回 。即返回的是[31,35)区间中的索引的位置。
  2. 如果继执行 find 方法 仍然按照上面的规则执行。

当将

Pattern pattern = Pattern.compile(""\\d\\d\\d\\d"");

改为分组的时候,有第一个一个括号就是第一组,第二个括号就是第二组。

Pattern pattern = Pattern.compile("(\\d\\d)(\\d\\d)");
  1. 根据规则,定位到满足规则的子字符串

  2. 找到后,将紫子非常的开始的索引记录到 matcher对象属性 int[] groups; groups[0] = 31 ,把该字符串的索引+1的值记录到 groups[1] = 35

  3. 记录第一组()匹配到的字符串 groups[2] = 31 groups[3] = 33

    因为匹配到的字符串为 1980 所以19为第一组所在的位置,又因为1所在的索引为 31,9 所在的索引为32所以groups[2] = 31 groups[3] = 33

  4. 记录第二组()匹配到的字符串 groups[3] = 33 groups[4] = 35

  5. 如果有更多的分组以此类推

如图
请添加图片描述

while中的代码修改为

while (matcher.find()){
    //匹配到的内容会在matcher.group(0)中
    System.out.println("找到 " + matcher.group(0));
    System.out.println("第一组()匹配的是 " + matcher.group(1));
    System.out.println("第二组()匹配的是 " + matcher.group(2));

}

运行结果为

请添加图片描述

小结:如果正则表达式有()即分组,取出的字符串规则为 group(0) 表示匹配到的字符串,group(1) 表示匹配到的子字符串中的第一组字符,group(2) 表示匹配到的子字符串中的第二组字符。注意!!分组的数不能越界

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

呀吖呀吖呀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值