【Java】Pattern 与 Matcher 类的常见应用

在 Java 编程中,我们经常需要处理字符串的匹配和替换操作。为了便捷地实现这些功能,Java 提供了 Pattern 类和 Matcher 类。Pattern 类用于定义正则表达式模式,而 Matcher 类用于在给定的输入字符串中进行匹配操作。

本文将介绍 Pattern 类和 Matcher 类在实际场景中常见的应用,以及列举一些常见的正则表达式示例。

基本定义

Java 正则表达式通过 java.util.regex 包下的 Pattern 类与 Matcher 类实现

Pattern 类的实例适应正则表达式的编译表示形式,指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher 对象,根据正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都会保留在匹配器中,因此多个匹配器可以共享同一模式。

因此,典型的调用顺序是:

  1. Pattern.compile() 生成编译后的正则表达式
  2. matcher() 生成匹配器
  3. matches() 执行匹配操作,并记录下匹配结果状态

单独用 Pattern 只能使用 Pattern.matches(String regex,CharSequence input) 这一种最基础最简单的匹配。

这种匹配的模式,只能满足一次性使用,不能重复使用,因此它的效率不高。但是从另一个角度来看,此类的实例是不可变的,可供多个并发线程安全使用。相比而言,Matcher 类的实例在并发下则没那么安全了。

Pattern 类

Pattern 类是 java.util.regex 包中的一个类,它用于定义正则表达式模式。正则表达式是一种强大的文本匹配工具,它可以用于在字符串中查找、替换或提取特定模式的文本。

Pattern 类用于创建一个正则表达式,也可以说创建一个匹配模式。它的构造方法是私有的,不可以直接创建,但可以通过静态方法 Pattern.complie(String regex) 这个简单工厂方法编译一个正则表达式模式。编译后的 Pattern 对象可以用于创建 Matcher 对象,后者用于在输入字符串中执行匹配操作。

Pattern p = Pattern.compile("\\w+");

如果直接使用 matches 静态方法,则对应返回一个 boolean 结果,表示是否匹配上目标表达式:

Pattern.matches("\\d+", "154234");

Matcher 类

Matcher类是Pattern类的内部类,用于在给定的输入字符串中执行匹配操作。Matcher对象可以通过调用Pattern对象的 matcher() 方法来创建,然后可以使用各种方法执行匹配操作。

Matcher m = Pattern.compile("\\w+").matcher("");

得到 Matcher 实例后,可以通过一系列的方法进行操作:

  • find():判断是否有下一组匹配成功的结果
  • lookingAt():起始位置是否匹配成功
  • group():等价于 group(0),返回匹配整个表达式的结果
  • start():等价于 start(0),返回整个结果的起始下标(包含)
  • end():等价于 end(0),返回整个结果的末尾下标(不包含)

下面给出一段实例代码:

@Test
public void testMatchSinglePattern() {String s1 = "vnkjslifgoia123aoivcmaiosdjfaio456vmldfjviodf789avoasdmfoi010";String s2 = "000vnkjslifgoia123aoivcmaiosdjfaio456vmldfjviodf789avoasdmfoi010";Pattern p = Pattern.compile("\\d+");Matcher m1 = p.matcher(s1);Matcher m2 = p.matcher(s2);// 包含字母,全匹配失败Assert.assertFalse(m1.matches());Assert.assertFalse(m2.matches());// 存在数字,有匹配的部分Assert.assertTrue(m2.find());// 开头部分是否匹配成功Assert.assertFalse(m1.lookingAt());Assert.assertTrue(m2.lookingAt());// 分别取出匹配的部分,每执行一次find()方法,获取一次下一个匹配项的信息if (m1.find()) {Assert.assertEquals(m1.group(), "123");Assert.assertEquals(m1.start(), 12);Assert.assertEquals(m1.end(), 15);}if (m1.find()) {Assert.assertEquals(m1.group(), "456");Assert.assertEquals(m1.start(), 31);Assert.assertEquals(m1.end(), 34);}
}

捕获组 group()

当匹配的正则表达式模式通过括号 () 分组创建了多个匹配单元时,成功匹配的结果则成为捕获组。对于一个 Matcher 对象匹配字符串 s 的结果来说, group()group(0) 对应匹配整个表达式,m.group() 的结果与 s.substring(m.start(), m.end()) 的结果是等价的。

通过 groupCount() 可以返回当前捕获组的数量,可以通过 group(1)group(2) 依次取出每个子单元匹配的内容。

start()end() 方法,则对应获取匹配内容的起始下标和末尾下标(与字符串一样,遵循“包头不包尾”原则)。类似的,start(1)end(1)start(2)end(2) 则是获取每个单元捕获组的首尾下标

下面给出一个例子来进行说明:

@Test
public void testMatchMultiPattern() {String s = "aaa111AAA bbb222 cccccc33CCCCCC  ";// 两组匹配内容,用括号()封装Pattern p = Pattern.compile("([a-z]+)(\\d+)([A-Z]+)");Matcher m = p.matcher(s);if (m.find()) {// 匹配模式中有三个()子序列,因此捕获组内count为3Assert.assertEquals(m.group(), "aaa111AAA");Assert.assertEquals(m.group(0), "aaa111AAA");Assert.assertEquals(m.groupCount(), 3);Assert.assertEquals(m.group(1), "aaa");Assert.assertEquals(m.group(2), "111");Assert.assertEquals(m.group(3), "AAA");Assert.assertEquals(m.start(), 0);Assert.assertEquals(m.start(1), 0);Assert.assertEquals(m.start(2), 3);Assert.assertEquals(m.start(3), 6);Assert.assertEquals(m.end(), 9);Assert.assertEquals(m.end(1), 3);Assert.assertEquals(m.end(2), 6);Assert.assertEquals(m.end(3), 9);}if (m.find()) {Assert.assertEquals(m.group(), "cccccc33CCCCCC");Assert.assertEquals(m.group(0), "cccccc33CCCCCC");Assert.assertEquals(m.groupCount(), 3);Assert.assertEquals(m.group(1), "cccccc");Assert.assertEquals(m.group(2), "33");Assert.assertEquals(m.group(3), "CCCCCC");Assert.assertEquals(m.start(), 17);Assert.assertEquals(m.start(1), 17);Assert.assertEquals(m.start(2), 23);Assert.assertEquals(m.start(3), 25);Assert.assertEquals(m.end(), 31);Assert.assertEquals(m.end(1), 23);Assert.assertEquals(m.end(2), 25);Assert.assertEquals(m.end(3), 31);}
}

范围匹配 region

region 用于设定查找范围,设定之后之前查找保存在 mathcer 中的结果清空,随后调用 find() 可在指定的下标范围中进行匹配。

@Test
public void testMatcherRegion() {String s = "aaa111AAACCCCCC  ";Pattern p = Pattern.compile("\\d+");Matcher m = p.matcher(s);m.region(0, 3);Assert.assertFalse(m.find());m.region(4, 10);m.find();Assert.assertEquals(m.group(), "11");
}

重置匹配 reset

顾名思义,reset 重置 matcher 实例中的匹配结果,重置后匹配记录被清空,需要再次调用 find() 方法重新进行匹配。

@Test
public void testMatcherReset() {String s = "aaa111AAA bbb222 cccccc33CCCCCC  ";// 两组匹配内容,用括号()封装Pattern p = Pattern.compile("[a-z]+");Matcher m = p.matcher(s);if (m.find()) {Assert.assertEquals(m.group(), "aaa");}if (m.find()) {Assert.assertEquals(m.group(), "bbb");}m.reset();if (m.find()) {Assert.assertEquals(m.group(), "aaa");}
}

其他常用的字符串操作

字符串分割 split

@Test
public void testStringSplit() {String s = "Good morning, ladies and gentleman!";// 按空格分割字符串,获取各个单词Pattern spacePattern = Pattern.compile("\\s+");String[] arr = spacePattern.split(s);Assert.assertEquals(arr[0], "Good");Assert.assertEquals(arr[1], "morning,");Assert.assertEquals(arr[2], "ladies");Assert.assertEquals(arr[3], "and");Assert.assertEquals(arr[4], "gentleman!");
}

字符串替换 replace

@Test
public void testStringReplacement() {String s = "apple-red,banana-yellow,grass-green,sky-blue";Pattern p = Pattern.compile("-");Assert.assertEquals(p.matcher(s).replaceAll(":"), "apple:red,banana:yellow,grass:green,sky:blue");Assert.assertEquals(p.matcher(s).replaceFirst("->"), "apple->red,banana-yellow,grass-green,sky-blue");
}

字符串匹配拼接 append

主要包括 appendReplacement()appendTail() ,两个方法执行的动作,简单来说:

  • appendReplacement() 将本次查找匹配到的字符串及其之前的字符追加到一个 StringBuffer 中去。
  • appendTail() 是将匹配后面剩下的未匹配的字符串追加到一个 StringBuffer 中。
@Test
public void testStringBuilderAppend(){Pattern pattern = Pattern.compile("a|b");Matcher matcher = pattern.matcher("aiiiibqqqqqafffffff@here.com");StringBuffer sb1 = new StringBuffer();StringBuffer sb2 = new StringBuffer();if (matcher.find()) {matcher.appendReplacement(sb1, matcher.group());Assert.assertEquals(sb1.toString(), "a");}if (matcher.find()) {matcher.appendReplacement(sb1, matcher.group());Assert.assertEquals(sb1.toString(), "aiiiib");}if (matcher.find()) {matcher.appendReplacement(sb1, matcher.group());Assert.assertEquals(sb1.toString(), "aiiiibqqqqqa");}matcher.appendTail(sb2);Assert.assertEquals(sb2.toString(), "fffffff@here.com");
}

参考文档

  • Java官方文档 - Pattern
  • API Reference Document

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

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

相关文章

Vue脚手架一站式搭建项目

一、什么是vue-cli 1.1如果你只是简单写几个Vue的Demo程序,那么你不需要VueCLI脚手架。 1.2.如果你在开发大型项目,那么你需要,并且必然需要使用VueCLI。 1.2.1使用Vue.js开发大型应用时,我们需要考虑代码目录结构、项目结构和…

安全基础 --- nodejs沙箱逃逸

nodejs沙箱逃逸 沙箱绕过原理:沙箱内部找到一个沙箱外部的对象,借助这个对象内的属性即可获得沙箱外的函数,进而绕过沙箱 前提:使用vm模块,实现沙箱逃逸环境。(vm模式是nodejs中内置的模块,是no…

凹凸贴图和法线贴图的区别

1、什么是凹凸贴图 凹凸贴图(bump mapping)是一种计算机图形学中的渲染技术,用于在给定的表面上模拟微小的凹凸纹理。通过在表面法线方向上微调每个像素的光照值,可以给平滑的表面增加视觉上的凹凸感。 在凹凸贴图中,每…

DockerKubernetes ❀ Service下Port端口区分

文章目录 概述案例 概述 在Kubernetes中,Service(svc)是一种抽象机制,用于将一组 Pod 暴露给其他应用程序或服务。Service 可以有三种类型的端口: nodePort:这是 Service 在节点上公开的端口。可以使用此…

TCP SOCKET (KGAS)处理过程

文章目录 1.缘起2.定位执行Job的session3.查看等待事件4. Oracle官方说明5.追踪问题6.根因 1.缘起 最近处理一个长时间运行的job,记录一下处理过程 2.定位执行Job的session SQL>SELECT * FROM DBA_JOBS_RUNNING;SID JOB FAILURES LAST_DATE …

基于微信小程序的校园生活管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言运行环境学生微信端的主要功能有:管理员的主要功能有:具体实现截图视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝1…

软考考试多少分算通过?

软考证书取得需要达到总分45分,每门科目满分为75分。因此,不要小看45分,在考试中获得这个分数并不容易。此外,软考要求一次性通过,如果没有通过,成绩将不被保留。因此,必须在一次考试中成功通过…

服务网格和性能优化:介绍如何通过服务网格提高微服务架构的性能和可扩展性

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

vue3项目学习一:创建vue3项目

创建vue3项目 一、使用vue-cli创建vue3项目1.安装vue-cli2.创建vue3项目 二、初始化项目结构三、导入element-ui 一、使用vue-cli创建vue3项目 1.安装vue-cli 先查看是否安装vue-cli 在cmd窗口输入vue -V查看版本,如果出现 则说明存在vue-cli,如果出现 则需要安…

Mac使用CMakeList编译ImGUi项目

文章目录 创建项目1.下载ImGui2.下载GLAD3.下载GLFW4.编译项目5.运行截图 创建项目 我这里创建一个demo,opengl这个是可以跨平台的,所以在mac上使用ImGui的opengl3示例 1.下载ImGui 我使用的是docking版本的,这个版本支持停靠功能&#xff…

算法 岛屿数量-(递归回溯)

牛客网 BM57. 二维矩阵,值为1表示岛屿,0表示海洋,求海洋中岛屿数量。 解题思路: 遍历二维数组,值为1增加岛屿数量记数,同时对此位置进行单独递归遍历上下左右4个方向,将数组坐标范围内同时值为1的元素置…

【面试篇】集合相关高频面试题

目录 1. ArrayList和LinkedList的区别?2. HashMap和HashTable的区别?1. ArrayList和LinkedList的区别? ArrayListLinkedList数据结构数组链表插入和删除在中间插入或删除元素时需要移动数组中的其他元素,时间复杂度为O(n)只需要调整指针,时间复杂度为O(1)访问元素通过索引…

Spring Boot 篇

1、为什么要用Spring Boot? 独立运行:Spring Boot而且内嵌了各种servlet容器,Tomcat、Jetty等,现在不再需要打成war包部署到容器中,Spring Boot只要打成一个可执行的jar包就能独立运行,所有的依赖包都在一…

Linux Qt5.15.2 编译QWebEngine源码支持音视频H264

背景 默认自带的QWebEngine 因版权问题不支持音视频功能,需要自己编译源码以支持。 平台:Linux(UOS V20 1050) Qt:5.15.2 准备工作 下载 Qt 5.15.2 对应版本源码,使用镜像网站或者Qt Maintenance Tool工…

【RPC】gRPC 安装及使用

本文记录下 Mac 安装 gRPC 的过程。 参考:官网 1. gRPC 安装 gRPC 安装步骤如下: 克隆 grpc 代码 git clone --recurse-submodules -b v1.58.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc注意:不要直接 git clone http…

计算机竞赛 深度学习YOLOv5车辆颜色识别检测 - python opencv

文章目录 1 前言2 实现效果3 CNN卷积神经网络4 Yolov56 数据集处理及模型训练5 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习YOLOv5车辆颜色识别检测 ** 该项目较为新颖,适合作为竞赛课题方向&#xff0…

一台PoE交换机可以为多少个设备提供供电?

如今在安防监控领域,许多网络设备都支持PoE供电。在网络监控工程中,为了节省布线成本并提高便捷性,大多数工程商选择使用PoE供电方案,也就是使用PoE交换机为监控摄像头提供电力。那么,一台功率输出以太网(P…

AI创作专家,免费的AI创作专家工具

AI创作专家是一种崭新的工具,它们利用先进的人工智能技术,帮助创作者和写手更轻松地应对创作挑战。这些工具不仅可以生成文字,还可以提供灵感、帮助构思和组织思路,使创作过程更加高效。 147GPT批量文章生成工具​www.147seo.com/…

深入探究序列化与反序列化:原理、应用和最佳实践

目录 什么是对象的序列化和反序列化序列化步骤反序列化步骤案例演示Java中哪些字段不能序列化序列化与反序列化的重要性序列化与反序列化的应用场景 什么是对象的序列化和反序列化 序列化(Serialization)是指将对象转化为字节流的过程,以便于…

想学嵌入式开发,薪资怎么样?

想学嵌入式开发,薪资怎么样? 对于嵌入式工程师来说呢,它重点学习内容就是首先一定要打好基础,如果从编程语言角度来讲,那么可以在语言上选C或者C,你可以选择其中任何一门语言作为你的入门。 最近很多小伙伴…