Java正则表达式完全指南

    • 一、正则表达式基础概念
      • 1.1 什么是正则表达式
      • 1.2 Java中的正则表达式支持
    • 二、正则表达式基本语法
      • 2.1 普通字符
      • 2.2 元字符
      • 2.3 预定义字符类
    • 三、Java中正则表达式的基本用法
      • 3.1 编译正则表达式
      • 3.2 创建Matcher对象并执行匹配
      • 3.3 常用的Matcher方法
    • 四、正则表达式高级应用
      • 4.1 分组与捕获
      • 4.2 反向引用
      • 4.3 贪婪匹配与非贪婪匹配
      • 4.4 零宽断言
    • 五、正则表达式在实际开发中的应用
      • 5.1 表单验证
        • 邮箱验证
        • 手机号验证
        • 身份证号码验证
      • 5.2 文本替换
        • 替换HTML标签
        • 敏感词过滤
      • 5.3 文本分割
        • 按逗号或空格分割
        • 按数字分割
    • 六、正则表达式性能优化
    • 七、常见问题与注意事项
    • 总结

正则表达式(Regular Expression,简称Regex)是一种强大的文本处理工具,它可以帮助开发者高效地进行字符串匹配、查找、替换和分割等操作。在Java中正则表达式的应用场景极为广泛,从简单的表单验证到复杂的文本解析,都离不开正则表达式的支持。虽然之前我也讲过正则表达式,但过于通用,今天本文将专门全面介绍Java中正则表达式的相关知识,从基础语法到高级应用,并结合丰富实例代码,带你深入理解和掌握这一强大工具。

一、正则表达式基础概念

1.1 什么是正则表达式

正则表达式是一种由字符和特殊符号组成的模式,用于描述字符串的特定格式规则。通过使用正则表达式,可以:

  • 检查字符串是否符合特定格式(如邮箱、手机号)
  • 从文本中提取感兴趣的内容(如URL、数字)
  • 替换文本中的特定部分
  • 将文本按特定规则分割

1.2 Java中的正则表达式支持

Java通过java.util.regex包提供对正则表达式的支持,主要涉及以下三个类:

  • Pattern:用于编译正则表达式,将正则表达式字符串编译为模式对象。
  • Matcher:用于执行匹配操作,对输入字符串进行解释和匹配操作。
  • PatternSyntaxException:用于处理正则表达式语法错误的异常类。

二、正则表达式基本语法

2.1 普通字符

普通字符包括没有显式指定为元字符的所有可打印和不可打印字符,它们直接匹配自身。例如:

  • abc 匹配字符串 “abc”
  • 123 匹配字符串 “123”

2.2 元字符

元字符是正则表达式中具有特殊含义的字符,常用的元字符及其含义如下:

元字符描述
.匹配除换行符以外的任意字符
^匹配字符串的开始位置
$匹配字符串的结束位置
*匹配前面的子表达式零次或多次
+匹配前面的子表达式一次或多次
?匹配前面的子表达式零次或一次
{n}匹配前面的子表达式恰好n次
{n,}匹配前面的子表达式至少n次
{n,m}匹配前面的子表达式至少n次,至多m次
[]匹配方括号中指定的任意一个字符
[^]匹配不在方括号中指定的任意一个字符
()标记一个子表达式的开始和结束位置
|表示或关系,匹配两个或多个选项之一

2.3 预定义字符类

为了简化常用字符类的定义,Java提供了一些预定义字符类:

预定义字符类等价表达式描述
\d[0-9]匹配一个数字字符
\D[^0-9]匹配一个非数字字符
\w[a-zA-Z_0-9]匹配一个单词字符(字母、数字、下划线)
\W[^a-zA-Z_0-9]匹配一个非单词字符
\s[ \t\n\x0B\f\r]匹配一个空白字符(空格、制表符、换行符等)
\S[^ \t\n\x0B\f\r]匹配一个非空白字符

三、Java中正则表达式的基本用法

3.1 编译正则表达式

在Java中使用正则表达式,首先需要将正则表达式字符串编译为Pattern对象:

import java.util.regex.Pattern;public class RegexExample {public static void main(String[] args) {// 编译正则表达式Pattern pattern = Pattern.compile("a.*c");}
}

3.2 创建Matcher对象并执行匹配

编译后的Pattern对象用于创建Matcher对象,然后通过Matcher对象执行匹配操作:

import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexExample {public static void main(String[] args) {// 编译正则表达式Pattern pattern = Pattern.compile("a.*c");// 创建Matcher对象Matcher matcher = pattern.matcher("abc");// 执行匹配操作boolean isMatch = matcher.matches();System.out.println("是否匹配: " + isMatch);  // 输出: true}
}

3.3 常用的Matcher方法

  • matches():尝试将整个输入序列与模式匹配。
  • find():在输入序列中查找下一个匹配的子序列。
  • group():返回当前匹配的子序列。
  • start():返回当前匹配的子序列的起始索引。
  • end():返回当前匹配的子序列的结束索引加1。

示例代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RegexExample {public static void main(String[] args) {String input = "Hello, world! Hello, Java!";Pattern pattern = Pattern.compile("Hello");Matcher matcher = pattern.matcher(input);// 查找所有匹配项while (matcher.find()) {System.out.println("匹配到: " + matcher.group() + ", 起始位置: " + matcher.start() + ", 结束位置: " + matcher.end());}}
}

输出结果:

匹配到: Hello, 起始位置: 0, 结束位置: 5
匹配到: Hello, 起始位置: 14, 结束位置: 19

四、正则表达式高级应用

4.1 分组与捕获

使用圆括号()可以将正则表达式中的部分内容分组,每个分组可以被单独捕获和引用。分组编号从1开始,0表示整个匹配结果。

示例:匹配并提取邮箱地址中的用户名和域名

import java.util.regex.Matcher;
import java.util.regex.Pattern;public class GroupExample {public static void main(String[] args) {String email = "test.user@example.com";String regex = "([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})";Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(email);if (matcher.matches()) {System.out.println("完整匹配: " + matcher.group(0));  // 整个匹配结果System.out.println("用户名: " + matcher.group(1));    // 第一组System.out.println("域名: " + matcher.group(2));      // 第二组}}
}

输出结果:

完整匹配: test.user@example.com
用户名: test.user
域名: example.com

4.2 反向引用

在正则表达式中,可以使用\n(n为数字)引用前面已经捕获的分组。例如,匹配重复的单词:

import java.util.regex.Matcher;
import java.util.regex.Pattern;public class BackreferenceExample {public static void main(String[] args) {String text = "hello hello world world";String regex = "\\b(\\w+)\\s+\\1\\b";Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(text);while (matcher.find()) {System.out.println("重复的单词: " + matcher.group());}}
}

输出结果:

重复的单词: hello hello
重复的单词: world world

4.3 贪婪匹配与非贪婪匹配

  • 贪婪匹配:默认情况下,正则表达式的量词(如*+{n,m})是贪婪的,会尽可能多地匹配字符。
  • 非贪婪匹配:在量词后面加上?,可以将贪婪匹配转换为非贪婪匹配,尽可能少地匹配字符。

示例:

import java.util.regex.Matcher;
import java.util.regex.Pattern;public class GreedyVsNonGreedy {public static void main(String[] args) {String text = "<html><body><h1>Hello</h1></body></html>";// 贪婪匹配String greedyRegex = "<.*>";Pattern greedyPattern = Pattern.compile(greedyRegex);Matcher greedyMatcher = greedyPattern.matcher(text);if (greedyMatcher.find()) {System.out.println("贪婪匹配: " + greedyMatcher.group());}// 非贪婪匹配String nonGreedyRegex = "<.*?>";Pattern nonGreedyPattern = Pattern.compile(nonGreedyRegex);Matcher nonGreedyMatcher = nonGreedyPattern.matcher(text);while (nonGreedyMatcher.find()) {System.out.println("非贪婪匹配: " + nonGreedyMatcher.group());}}
}

输出结果:

贪婪匹配: <html><body><h1>Hello</h1></body></html>
非贪婪匹配: <html>
非贪婪匹配: <body>
非贪婪匹配: <h1>
非贪婪匹配: </h1>
非贪婪匹配: </body>
非贪婪匹配: </html>

4.4 零宽断言

零宽断言用于在特定位置匹配某些内容,但不包含匹配的内容本身。Java支持四种零宽断言:

断言类型语法描述
正向先行断言(?=pattern)匹配后面跟着pattern的位置
负向先行断言(?!pattern)匹配后面不跟着pattern的位置
正向后行断言(?<=pattern)匹配前面是pattern的位置
负向后行断言(?<!pattern)匹配前面不是pattern的位置

示例:匹配所有以"ing"结尾的单词

import java.util.regex.Matcher;
import java.util.regex.Pattern;public class LookaroundExample {public static void main(String[] args) {String text = "running jumping swimming";String regex = "\\b\\w+(?=ing\\b)";Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(text);while (matcher.find()) {System.out.println("匹配到: " + matcher.group());}}
}

输出结果:

匹配到: run
匹配到: jump
匹配到: swim

五、正则表达式在实际开发中的应用

5.1 表单验证

正则表达式常用于表单验证,确保用户输入的数据符合预期格式。

邮箱验证
public static boolean isValidEmail(String email) {String regex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";return Pattern.matches(regex, email);
}
手机号验证
public static boolean isValidPhone(String phone) {String regex = "^1[3-9]\\d{9}$";return Pattern.matches(regex, phone);
}
身份证号码验证
public static boolean isValidIdCard(String idCard) {String regex = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$";return Pattern.matches(regex, idCard);
}

5.2 文本替换

使用正则表达式可以方便地进行文本替换操作。

替换HTML标签
public static String removeHtmlTags(String html) {String regex = "<[^>]+>";return html.replaceAll(regex, "");
}
敏感词过滤
public static String filterSensitiveWords(String text) {String[] sensitiveWords = {"敏感词1", "敏感词2", "敏感词3"};String regex = String.join("|", sensitiveWords);return text.replaceAll(regex, "***");
}

5.3 文本分割

使用正则表达式可以按复杂规则分割文本。

按逗号或空格分割
public static String[] splitText(String text) {String regex = "[,\\s]+";return text.split(regex);
}
按数字分割
public static String[] splitByNumbers(String text) {String regex = "\\d+";return text.split(regex);
}

六、正则表达式性能优化

  1. 编译一次,多次使用:避免在循环中重复编译相同的正则表达式,应将编译后的Pattern对象缓存并复用。
  2. 简化正则表达式:复杂的正则表达式会降低匹配效率,尽量使用简单、明确的表达式。
  3. 避免过度使用回溯:贪婪匹配和反向引用可能导致大量回溯,影响性能。
  4. 优先使用String类的方法:对于简单的字符串操作,如startsWith()endsWith()indexOf()等,应优先使用String类的方法,比正则表达式效率更高。

七、常见问题与注意事项

  1. 转义字符问题:在Java字符串中使用正则表达式时,需要注意转义字符。例如,匹配点号.需要写成\\.,匹配反斜杠\需要写成\\\\
  2. 性能问题:复杂的正则表达式可能导致性能问题,特别是在处理大量数据时。
  3. 边界问题:使用^$时要注意是否需要匹配整个字符串,还是只需要匹配部分内容。
  4. Unicode支持:Java默认支持Unicode字符,但在处理非ASCII字符时需要特别注意。

总结

正则表达式是Java中强大的文本处理工具,掌握正则表达式的基本语法和Java中的使用方法,对于提高字符串处理效率和开发质量至关重要。本文从基础概念入手,详细介绍了正则表达式的语法、Java中的API使用、高级应用场景以及性能优化等方面的内容,希望你在今后熟练使用尽量掌握。

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

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

相关文章

缓存击穿、缓存雪崩、缓存穿透以及数据库缓存双写不一致问题

在项目中&#xff0c;我们所需要的数据通常存储在数据库中&#xff0c;但是数据库的数据保存在硬盘上&#xff0c;硬盘的读写操作很慢&#xff0c;为了避免直接访问数据库&#xff0c;我们可以使用 Redis 作为缓存层&#xff0c;缓存通常存储在内存中&#xff0c;内存的读写速度…

可灵2.1 vs Veo 3:AI视频生成谁更胜一筹?

在Google发布Veo 3几天后,可灵显然感受到了压力,发布了即将推出的视频模型系列可灵 2.1的早期体验版。 据我了解,有三种不同的模式: 可灵 2.1 标准模式: 720p分辨率 仅支持图像转视频(生成更快,一致性更好) 5秒视频仍需20积分 可灵 2.1 专业模式: 1080p分辨率 仅在图…

解决Docker存储空间不足问题

虚拟机磁盘扩展实战&#xff1a;解决Docker存储空间不足问题 问题背景 在虚拟机中运行的Linux系统上&#xff0c;Docker服务因根分区空间不足而无法正常运行。初始状态如下&#xff1a; [rootlocalhost ~]# df -h / 文件系统 容量 已用 可用 已用% 挂载点…

Redis 中如何保证缓存与数据库的数据一致性?

在 Redis 中保证缓存与数据库的数据一致性&#xff0c;需结合业务场景选择以下策略&#xff1a; 核心策略总结 Cache Aside&#xff08;旁路缓存&#xff09;模式 读操作&#xff1a;先查缓存&#xff0c;未命中则查数据库并写入缓存。写操作&#xff1a;先更新数据库&#xf…

晶振频率稳定性:5G 基站与航天设备的核心竞争力

在当今科技飞速发展的时代&#xff0c;电子设备的性能和可靠性至关重要。晶振作为电子设备中的核心部件&#xff0c;为系统提供精确的时间和频率基准。晶振的频率稳定性直接影响着设备的整体性能&#xff0c;从日常生活中广泛使用的智能手机、智能穿戴设备&#xff0c;到对精度…

PDFGear——完全免费且功能强大的PDF处理软件

关键词 &#xff1a;PDFGear、免费、跨平台、多功能、OCR 概要 &#xff1a;PDFGear是一款完全免费且功能强大的PDF处理软件&#xff0c;支持Windows、macOS、iOS和Android等多平台使用。它集PDF阅读、编辑、格式转换、OCR识别及AI智能助手于一体&#xff0c;满足用户多样化文档…

【笔记】在 MSYS2(MINGW64)中正确安装 Rust

#工作记录 1. 环境信息 Windows系统: MSYS2 MINGW64当前时间: 2025年6月1日Rust 版本: rustc 1.87.0 (17067e9ac 2025-05-09) (Rev2, Built by MSYS2 project) 2. 安装步骤 步骤 1: 更新系统包数据库并升级已安装的包 首先&#xff0c;确保我们的 MSYS2 系统是最新状态。打…

WIN11+VSCODE搭建的c/c++环境调试报错解决

解决调试报错 前面win11vscode搭建的c/c环境&#xff0c;ctrlshiftB生成正常&#xff0c;cttlF5运行正常。今天打断点逐步调试时报错&#xff0c;提示找不到库文件。解决方案如下&#xff1a; 下载mingw-w64源码库&#xff1a;&#xff08;两种途径&#xff09; 通过MSYS2 UC…

React项目在ios和安卓端要做一个渐变色背景,用css不支持,可使用react-native-linear-gradient

以上有个模块是灰色逐渐到白的背景色过渡 如果是css&#xff0c;以下代码就直接搞定 background: linear-gradient(180deg, #F6F6F6 0%, #FFF 100%);但是在RN中不支持这种写法&#xff0c;那应该写呢&#xff1f; 1.引入react-native-linear-gradient插件&#xff0c;我使用的是…

android-studio-2024.3.2.14如何用WIFI连接到手机(给数据线说 拜拜!)

原文&#xff1a;Android不用数据线就能调试真机的方法—给数据线说 拜拜&#xff01;&#xff08;adb远程调试&#xff09; android-studio-2024.3.2.14是最新的版本&#xff0c;如何连接到手机&#xff0c;可用WIFI&#xff0c;可不用数据线&#xff0c;拜拜 第一步&#xf…

【前端】JS引擎 v.s. 正则表达式引擎

JS引擎 v.s. 正则表达式引擎 它们的转义符都是\ 经过JS引擎会进行一次转义 经过正则表达式会进行一次转义在一次转义中\\\\\的转义过程&#xff1a; 第一个 \ (转义符) 会“吃掉”第二个 \&#xff0c;结果是得到一个字面量的 \。 第三个 \ (转义符) 会“吃掉”第四个 \&#x…

ReactHook有哪些

React 中常用的 Hooks 列表及用法 React Hooks 是 React 16.8 版本引入的一项重要特性&#xff0c;它极大地简化和优化了函数组件的开发过程。以下是 React 中常用的 Hooks 列表及其详细用法&#xff1a; 1. useState useState 是用于在函数组件中添加状态的 Hook。通过调用…

【PyQt5】PyQt5初探 - 一个简单的例程

PyQt5初探 - 一个简单的例程 引言一、安装配置二、使用2.1 PyQt5简单例程2.2 与c Qt深入对比 三、相关教程 引言 PyQt5是一个比较流行的Python图形用户界面(GUI)库&#xff0c;它基于Qt库&#xff08;一个跨平台的C库&#xff0c;用于开发应用程序的图形界面&#xff09;为Pyt…

图文详解Java并发面试题

文章目录 1、并发与并行2、线程安全3、线程、进程、协程4、线程间通信5、线程创建方式6、8G内存创建的线程数7、普通Java程序含有的线程8、start()、run()9、线程调度、6种状态、强制停止线程、上下文切换10、守护线程、用户线程11、 volatile 、synchronized12、sleep() 、 wa…

飞牛fnNAS存储空间模式详解

目录 一、NAS的存储空间 二、多硬盘对NAS速度的提升原理 三、多硬盘对数据安全的提升原理 四、多硬盘对容量的提升原理 五、磁盘阵列模式 六、飞牛NAS支持的存储模式 七、具体如何选择存储空间模式 在数字化时代,数据是个人和企业发展的核心资产,但面临硬盘损坏、病毒…

OpenCv高阶(二十)——dlib脸部轮廓绘制

文章目录 一、人脸面部轮廓绘制代码实现1、定义绘制直线段的函数2、定义绘制凸包轮廓的函数3、读取输入图像4、初始化dlib的人脸检测器5、使用检测器在图像中检测人脸&#xff08;参数0表示不进行图像缩放&#xff09;6、加载dlib的68点人脸关键点预测模型7、遍历检测到的每个人…

WEBSTORM前端 —— 第3章:移动 Web —— 第3节:移动适配

目录 一、移动Web基础 1.谷歌模拟器 2.屏幕分辨率 3.视口 4.二倍图 二、适配方案 三、rem 适配方案 四、less 1.less – 简介 2.less – 注释 3.less – 运算 4.less – 嵌套 5.less – 变量 6.less – 导入 7.less – 导出 8.less – 禁止导出 五…

Altium Disigner(16.1)学习-原理图绘制以及必要操作

一、下载软件 通过网盘分享的文件&#xff1a;Altium Designer 16.zip 链接: https://pan.baidu.com/s/1uBHeoJJ-iA2tXw3NRjCcdA?pwd7c3h 提取码: 7c3h 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --来自百度网盘超级会员v5的分享 二、建立工程 添加proje…

AI炼丹日志-25 - OpenAI 开源的编码助手 Codex 上手指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇&#xff1a; MyBatis 更新完毕目前开始更新 Spring&#xff0c;一起深入浅出&#xff01; 大数据篇 300&#xff1a; Hadoop&…

Redis:安装与常用命令

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Redis &#x1f525; 安装 Redis 使⽤apt安装 apt install redis -y⽀持远程连接 修改 /etc/redis/redis.conf 修改 bind 127.0.0.1 为 bind 0.0.0.0 修改 protected-mode yes 为 protected-mo…