Java 正则表达式【匹配与分组基本原理】

简介

        我们一般使用正则表达式是用来处理字符串的,不管是实际的开发中还是我们的算法竞赛中,使用正则表达式绝对可以大大提升我们的效率。

        正则表达式(regular expression)其实就是对字符串进行模式匹配的技术。


快速入门

我们这里演示一个案例,使用正则表达式匹配下面字符串中的所有英文单词:


import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexDemo01 {public static void main(String[] args) {String content = "1995年,互联网的蓬勃发展给了Oak机会。业界为了使死板、单调的" +"静态网页能够“灵活”起来,急需一种软件技术来开发一种程序,这种程序可以通过" +"网络传播并且能够跨平台运行。于是,世界各大IT企业为此纷纷投入了大量的人力" +"、物力和财力。这个时候,Sun公司想起了那个被搁置起来很久的Oak,并且重新审" +"视了那个用软件编写的试验平台,由于它是按照嵌入式系统硬件平台体系结构进行编" +"写的,所以非常小,特别适用于网络上的传输系统,而Oak也是一种精简的语言,程" +"序非常小,适合在网络上传输。Sun公司首先推出了可以嵌入网页并且可以随同网页" +"在网络上传输的Applet(Applet是一种将小程序嵌入到网页中进行执行的技术)" +",并将Oak更名为Java。5月23日,Sun公司在Sun world会议上正式发布Java和" +"HotJava浏览器。IBM、Apple、DEC、Adobe、HP、Oracle、Netscape和微软" +"等各大公司都纷纷停止了自己的相关开发项目,竞相购买了Java使用许可证,并为自" +"己的产品开发了相应的Java平台。";// 提取文章中所有英文单词Pattern pattern = Pattern.compile("[a-zA-Z]+");Matcher matcher = pattern.matcher(content);while (matcher.find()){// 匹配到的内容都会放到 matcher.group(0)里面System.out.println(matcher.group(0));}}
}

运行结果: 

Oak
IT
Sun
Oak
Oak
Sun
Applet
Applet
Oak
Java
Sun
Sun
world
Java
HotJava
IBM
Apple
DEC
Adobe
HP
Oracle
Netscape
Java
Java

同理,如果我们想要获取字符串中所有的数字获取字符串中所有字符串或者数字,只需要这样修改:

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

        要知道,我们自己实现的话会很复杂,我自己尝试过,比如实现提取所有英文字符,我们需要这样来设计:

  • 把字符串转为 char 数组
  • 遍历数组,判断字符的 ASCII码是否在 [a,z] , [A,Z]范围内
  • 判断英文字符前的字符是否为非英文字符,如果是在字符前添加空格(防止结果连成一片)
  • 判断英文字符后的字符是否为非英文字符,如果是在字符后添加空格(防止结果连成一片)

        可以看到,我们自己编写程序去实现确实是十分复杂,所以为什么不学习正则表达式呢,取英文字符是比较简单的案例,如果遇到验证邮箱、手机号、身份证号、ip地址、提取字符串等需要各种字符串处理算法的时候,手写算法是十分烧脑的,最好的办法就是找到规律使用正则表达式,提高开发效率!

        除此之外,我们学习的网络爬虫在做数据处理的时候,比如各种新闻标题、产品标题、商品评论,这些文本通常都是在超链接或者一些特殊标签内部,这时候我们直接使用正则表达式就可以很轻松地实现标签内文本的提取,这样,我们只需要专心爬虫的代码,而不需要过于担心爬到数据后的数据处理问题了。



底层实现

        我们这里主要讨论一下 Java正则表达式中,matcher.find()matcher.group(int group) 的底层是怎么实现的。

案例

找出四个数字连在一起的子串

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 regex = "\\d\\d\\d\\d";Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(content);while (matcher.find()){System.out.println(matcher.group());   // 无参时默认就是 group(0)}

输出结果:

1998
1999
3443
9889

 

我们开始分析代码以及通过debug分析源码:

matcher.find() & matcher.group() 原理

matcher.group(0)

  • 首先,根据我们给它的规则去匹配,定位到满足要求的子字符串位置(比如1998)
  • 然后,将子字符串的开始的索引记录到 matcher 对象的属性中去(int[] groups)。
    •  groups[0] = 0 , 把该子字符串结束的索引+1的值记录到 groups[1]中去,groups[1] = 4

我们Matcher类的属性 int[] groups 的初始大小为 20 ,初始值均为 -1. 

  •  同时记录属性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();}
  • 此时我们调用 mactcher.group(0) 的话,很明显会返回 getSubSequence(groups[0],groups[1]).toString(); 相当于根据 groups[0]=0 和 groups[1]=4 记录的位置来截取字符串 ,注意是左闭右开的 [0,4)。 此时,输出 1998.

继续下一次 matcher.find() 方法,这次定位到了 1999 这个位置:

  • 此时,groups[0] = 31, groups[1] = 35 ,oldLast = 35 。
  • 同样再次调用 matcher.group(0) , 输出 1999。

到这里,我们基本了解了 group(0) 的含义,每次调用matcher.group(0) 它都会去查找字符串中的子串首尾下标,这些下标存在 groups数组中 ,而且首下标永远都是 groups[0] ,尾下标永远都是 groups[1] 。

但是如果我们调用的是 group(1)、或者group(n) 又会是怎样的情况呢?

matcher.group(n)

其实,group(n) 涉及到的是一个分组的概念,体现在代码中的匹配语句上就是括号,我们对上面的匹配语句做一个修改:

String regex = "(\\d\\d)(\\d\\d)";Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(content);while (matcher.find()){System.out.println(matcher.group());   // 无参时默认就是 group(0)System.out.println(matcher.group(1));System.out.println(matcher.group(2));}

输出结果:

group(0) = 1998
group(1) = 19
group(2) = 98
group(0) = 1999
group(1) = 19
group(2) = 99
group(0) = 3443
group(1) = 34
group(2) = 43
group(0) = 9889
group(1) = 98
group(2) = 89

 此时,我们再从 matcher.find()  开始分析:

  • 首先,根据我们给它的规则去匹配,定位到满足要求的子字符串位置(比如(19)(98)
  • 然后,将子字符串的开始的索引记录到 matcher 对象的属性中去(int[] groups)。
    •  groups[0] = 0 , 把该子字符串结束的索引+1的值记录到 groups[1]中去,groups[1] = 4
    • 记录1组()匹配到的子串下标到 groups[2] = 0 , groups[3] = 2。
    • 记录2组()匹配到的子串下标到 groups[4] = 2 , groups[5] = 4。
    • 如果还有更多组,以此类推...

  • 到这里,我们基本了解了分组的实现原理:groups数组负责存储子字符串的下标以及子字符串内每组子串的首尾下标,我们的 getSubSequence(groups[group * 2], groups[group * 2 + 1]) 方法会去根据 matcher.group(int group) 给的参数 group 去查找对应groups数组的首尾下标,从而调用String.substring(start,end) 截取出每组对应的子串。

 不得不说,getSubSequence(groups[group * 2], groups[group * 2 + 1]),这个参数的设置确实十分巧妙!

总结

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

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

  • group(0) 代表匹配到的子字符串,不分组
  • group(1) 代表匹配到的子字符串第1组
  • group(2) 代表匹配到的子字符串第2组
  • ...
  • 但是参数不能越界,不能超过分组数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/32614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第三篇|金融人数据来源有哪些

数据对于金融行业真的很重要&#xff0c;那么金融人有哪些途径查数据呢&#xff1f; 国内&#xff1a; 1. 国家统计局 这个应该是无论什么行业都使用最频繁的网站&#xff0c;每个月都会固定发上个月资产投资数据 、工业增加值和利润数据等常规数据&#xff0c;其他数据也会…

什么是分布式系统,如何学习分布式系统

正文 虽然本人在前面也写过好几篇分布式系统相关的文章&#xff0c;主要包CAP理论&#xff0c;分布式储存与分布式事务&#xff0c;但对于分布式系统&#xff0c;并没有一个跟清晰的概念。分布式系统涉及到很多的技术、理论与协议&#xff0c;很多人也说&#xff0c;分布式系统…

Docker 安装和架构说明

Docker 并非是一个通用的容器工具&#xff0c;它依赖于已存在并运行的Linux内核环境。 Docker实质上是在已经运行的Liunx下制造了一个隔离的文件环境&#xff0c;因此他的执行效率几乎等同于所部署的linux主机。因此Docker必须部署在Linux内核系统上。如果其他系统想部署Docke…

hutool 导出复杂表头excel

假如已这样的表头导出数据 1.把包含表头的excel添加到项目资源目录 2.编写代码读取表头所在sheet,并且加入需导出的数据 /*** 导出excel*/public static void downloadExcel(List<List<Object>> list, HttpServletResponse response) throws IOException {/*Strin…

wpf 3d 坐标系和基本三角形复习

wpf 3d 坐标系的描述见此&#xff0c; WPF 3d坐标系和基本三角形_wpf 坐标系_bcbobo21cn的博客-CSDN博客 X轴正向向右&#xff0c;Y轴正向向上&#xff1b;Z轴&#xff0c;正向是从屏幕里边出来&#xff0c;负向是往屏幕里边去&#xff1b;坐标原点是在呈现区域的中心&#x…

知识付费系统开发:构建高效智能的付费内容平台

随着数字化时代的来临&#xff0c;知识付费正迅速崭露头角&#xff0c;为知识创作者和求知者带来了全新的商机。在这个背景下&#xff0c;开发一款高效智能的知识付费系统成为了一项重要的任务。本文将深入探讨如何基于Python编程语言和相关技术构建一个智能的知识付费内容平台…

mac arm 通过brew搭建 php+nginx+mysql+xdebug

1.安装nginx brew install nginx //安装brew services start nginx //启动2.安装php brew install php7.4 //安装export PATH"/opt/homebrew/opt/php7.4/bin:$PATH" //加入环境变量 export PATH"/opt/homebrew/opt/php7.4/sbin:$PATH"brew serv…

【百度翻译api】中文自动翻译为英文

欸&#xff0c;最近想做一些nlp的项目&#xff0c;做完了中文的想做做英文的&#xff0c;但是呢&#xff0c;国内爬虫爬取的肯定都是中文 &#xff0c;爬取外网的技术我没有尝试过&#xff0c;没有把握。所以我决定启用翻译&#xff0c;在这期间chatGPT给了我非常多的方法&…

【枚举】CF1660 D

Problem - 1660D - Codeforces 题意&#xff1a; 思路&#xff1a; 思路巨简单&#xff0c;代码也wa了很多发才过&#xff0c;都是因为细节.... 很显然&#xff0c;要根据0分段处理 对于每一段&#xff0c;枚举去掉左边段还是右边段&#xff0c;左边段是 l 到第一个负数&am…

网络加速与文件传输软件:如何通过优化网络提升文件传输速度

在信息化社会&#xff0c;文件传输是人们生活和工作中必不可少的一个环节。但是&#xff0c;由于网络环境的多样性和传输过程中可能出现的各种问题&#xff0c;文件传输速度经常受到影响。因此&#xff0c;如何优化网络以提高文件传输速度成为了一个重要的课题。本文将探讨网络…

力扣:59. 螺旋矩阵 II(Python3)

题目&#xff1a; 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全…

windows使用/服务(13)戴尔电脑怎么设置通电自动开机

戴尔pc机器通电自启动 1、将主机显示器键盘鼠标连接好后&#xff0c;按主机电源键开机 2、在开机过程中按键盘"F12",进入如下界面&#xff0c;选择“BIOS SETUP” 3、选择“Power Management” 4、选择“AC Recovery”&#xff0c;点选“Power On”&#xff0c;点击“…

解决:django设置DEBUG=false时出现的问题

首先&#xff0c;我用的是django4.2&#xff0c;python3.10版本 本来&#xff0c;如果在settings.py中使用 DEBUG True&#xff0c;那么什么问题也没有&#xff0c;当然&#xff0c;这属于调试模式。 DEBUG True TEMPLATE_DEBUG DEBUGSTATIC_URL /static/ STATICFILES_DI…

七. 定时器

定时器 1. EPIT定时器(1) 特征&#xff1a;(2) 结构&#xff1a;(3) 工作模式&#xff1a;(4) 寄存器(5) 配置步骤(6) 定时器消抖 2. GPT 定时器(1) 特征(2) 结构(3) 工作模式(4) 寄存器<1> GPTx_CR 配置<2> GPTx_PR 分频<3> GPTx_SR 状态<4> GPTx_CNT…

Java集合知识回顾:从分类到工具类,掌握精髓

文章目录 1. 集合的分类2. Collection 接口3. Map 接口4. 泛型5. Collections 工具类总结 在Java编程世界中&#xff0c;集合是一项极为重要的知识&#xff0c;为我们的程序设计提供了强大的数据结构和处理手段。在本篇文章中&#xff0c;我们将回顾集合的分类以及相关的重要概…

接口测试自动化:简化测试流程,提升效率

接口测试自动化&#xff1a;简化测试流程&#xff0c;提升效率 什么是接口测试自动化&#xff1f; 接口测试自动化是指使用特定的工具和技术来自动化执行接口测试的过程。通过编写脚本&#xff0c;自动化工具可以模拟用户与软件系统的交互&#xff0c;验证接口的功能和性能。…

web应用越用越卡怎么办

简介 如果你的网页应用越用越卡,你就有理由怀疑存在内存泄露 在开发Web应用程序时&#xff0c;经常会遇到内存泄漏的问题&#xff0c;这可能导致应用程序的性能下降或崩溃。Chrome浏览器提供了一个内存面板&#xff0c;可以帮助我们识别并解决这些问题。本文将介绍如何使用Chr…

工程优化问题之三杆桁架设计研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Unity UI.Image 六边形+流光 Shader

效果图 参考代码 Shader"Custom/HexFlowImage" {Properties{[PerRendererData] _MainTex ("Sprite Texture", 2D) "white" {}_Color ("Tint", Color) (1,1,1,1)_StencilComp ("Stencil Comparison", Float) 8_Stencil (…

YOLO v8目标跟踪详细解读(一)

在此之前&#xff0c;我们已经对yolo系列做出了详细的探析&#xff0c;有兴趣的朋友可以参考yolov8等文章。YOLOV8对生态进行了优化&#xff0c;目前已经支持了分割&#xff0c;分类&#xff0c;跟踪等功能&#xff0c;这对于我们开发者来说&#xff0c;是十分便利。今天我们对…