正则表达式 – 教程(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
 - 《从零手撸:仿小红书(微服务架构)》 已完结,基于
 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
 截止目前, 星球 内专栏累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3700+ 小伙伴加入学习 ,欢迎点击围观
前言
在编程和数据处理的世界中,正则表达式(Regular Expression,简称 regex 或 regexp)如同一把瑞士军刀,能够精准地定位、提取和操作文本中的模式。无论是验证用户输入的邮箱格式、解析日志文件中的关键信息,还是批量替换文档中的特定内容,正则表达式都能以简洁高效的方式完成任务。然而,对于许多编程初学者而言,正则表达式既神秘又复杂,仿佛需要掌握某种“密码学”才能驾驭。本文将通过循序渐进的讲解、生动的比喻和实际案例,帮助读者逐步掌握这一强大的工具。
基础概念与核心语法
什么是正则表达式?
正则表达式是一种描述文本模式的符号语言,它通过特定的符号和规则,将模糊的“文本特征”转化为可执行的代码逻辑。例如,要匹配一个邮箱地址,正则表达式可以写成 ^\w+@\w+\.\w+$,这个模式能精准识别类似 user@example.com 的字符串,但会拒绝 user@.com 这样的无效格式。
形象比喻:
你可以将正则表达式想象成一张“寻宝图”,每个符号代表一个线索,指引程序在文本中寻找符合规则的“宝藏”。而程序员的任务,就是绘制这张图的路径。
基础语法:字符与元字符
1. 字符的直接匹配
正则表达式中最简单的用法是直接匹配字符。例如:
hello匹配字符串中的“hello”404匹配数字“404”
注意:
如果要匹配特殊字符(如 .、*、$),需用反斜杠 \ 转义。例如,匹配字符串中的句号需写成 \.。
2. 元字符:赋予表达式“超能力”
元字符是正则表达式的关键,它们能定义更复杂的匹配逻辑:
| 元字符 | 含义                     | 示例                   |
|--------|--------------------------|------------------------|
| .    | 匹配任意单个字符(除换行符) | a.c 匹配 "abc"、"a2c" |
| *    | 匹配前一个字符的零次或多次 | a*b 匹配 "b"、"aab"  |
| +    | 匹配前一个字符的一次或多次 | a+b 匹配 "ab"、"aaab" |
| ?    | 匹配前一个字符的零次或一次 | colou?r 匹配 "color" 或 "colour" |
| ^    | 匹配字符串的开头         | ^start 匹配以 "start" 开头的文本 |
| $    | 匹配字符串的结尾         | end$ 匹配以 "end" 结尾的文本 |
案例:
要匹配以 http 开头的 URL,可以写成 ^http。若需同时匹配 https,则需 ^https?(其中 ? 允许 s 出现 0 次或 1 次)。
字符类:定义可选范围
1. 基本字符类
[abc]:匹配 a、b 或 c 中的一个字符[0-9]:匹配任意数字(等价于\d)[A-Z]:匹配任意大写字母
案例:
匹配一个字母开头的邮箱:
^[a-zA-Z][\w.]+@\w+\.\w+$
2. 否定字符类
[^abc] 匹配不在集合内的字符。例如,[^0-9] 匹配非数字字符。
进阶技巧:量词与分组
量词的精准控制
量词(如 *、+、?)可以调整匹配的次数,但需注意“贪婪”与“非贪婪”模式:
- 贪婪模式(默认):尽可能匹配更多字符。例如,
<.*>在匹配<div>content</div>时会匹配到</div>,导致意外结果。 - 非贪婪模式:添加 
?后,如<.*?>,则仅匹配最短的div标签。 
案例:
正确提取 HTML 标签:
<.*?>
分组与捕获
通过圆括号 () 可以创建分组,用于:
- 捕获内容:例如,
(\d{4})可捕获年份,如2023。 - 复用模式:如 
(\w+)\s\1匹配重复的单词,如 "test test"。 
案例:
提取日期中的年、月、日:
(\d{4})-(\d{2})-(\d{2})
高级技巧:前瞻与后顾
前瞻(Lookahead)
前瞻允许检查匹配后的文本,但不将其包含在结果中:
- 正向前瞻:
a(?=b)匹配后面跟着b的a,例如cab中的a。 - 负向前瞻:
a(?!b)匹配后面不跟b的a,例如cat中的a。 
案例:
匹配不以 .com 结尾的邮箱:
^[^@]+\@[^@]+\.(?!com$)[a-z]+$
后顾(Lookbehind)
与前瞻类似,但检查匹配前的文本:
- 正向后顾:
(?<=a)b匹配前面是a的b。 - 负向后顾:
(?<!a)b匹配前面不是a的b。 
案例:
匹配 id=123 中的 123,且确保前缀是 id=:
(?<=id=)\d+
实战案例:常见场景的应用
案例 1:验证邮箱格式
邮箱的正则表达式需满足:
- 以字母开头,允许包含 
.、_、- - 后跟 
@和域名,域名包含至少一个. 
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
解析:
^[a-zA-Z0-9._%+-]+:开头部分允许字母、数字及特殊字符。@[a-zA-Z0-9.-]+:域名部分,允许字母、数字、点和横杠。\.[a-zA-Z]{2,}$:确保以至少两个字母结尾(如.com、.org)。
案例 2:提取电话号码
假设电话号码格式为 +86-138-1234-5678:
\+\d{2}-\d{3}-\d{4}-\d{4}
优化版本:
允许可选的国家代码和分隔符:
(\+\d{1,3}[- ]?)?(\d{3}[- ]?){2}\d{4}
案例 3:替换 HTML 标签
使用正则表达式删除所有 HTML 标签:
text.replace(/<.*?>/g, "");
工具与调试建议
推荐工具
- Regex101:实时测试正则表达式,支持高亮匹配和解释模式。
 - VS Code 内置搜索:通过 
/正则表达式/格式进行文件查找替换。 
调试技巧
- 逐步简化:从简单模式开始,逐步添加复杂条件。
 - 使用 
x标志(如/pattern/x):允许在正则中添加空格和注释。 - 测试边界条件:例如,验证 
0、空字符串或特殊符号是否符合预期。 
结论与学习建议
总结
正则表达式是文本处理领域的核心工具,其威力在于通过符号组合实现复杂逻辑。从基础的字符匹配到高级的前瞻后顾,掌握正则表达式需要:
- 理解元字符的含义:如 
.、*、()的作用。 - 通过案例实践:从邮箱验证、文本提取到数据清洗,实战是提升的关键。
 - 善用工具辅助:Regex101 等工具能显著降低调试成本。
 
学习路径建议
- 初级阶段:学习基础语法和常见模式(如邮箱、电话号码)。
 - 中级阶段:掌握分组、前瞻后顾及替换功能。
 - 高级阶段:探索 Unicode 支持、性能优化和跨语言差异(如 JavaScript 与 Python 的语法差异)。
 
结语
正则表达式 – 教程的完成,不仅是技术的掌握,更是思维模式的转变。它教会我们如何将模糊的需求转化为精确的逻辑规则,如同在文本的迷宫中铺设一条条清晰的路径。从今天起,不妨尝试用正则表达式解决一个实际问题,你可能会发现:那些曾让你头疼的文本处理任务,原来可以如此优雅而高效!
(字数:约 1800 字)