正则表达式 – 教程(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言
在编程和数据处理的世界中,正则表达式(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 字)