正则表达式 – 教程(长文讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 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 标签:

<.*?>

分组与捕获

通过圆括号 () 可以创建分组,用于:

  1. 捕获内容:例如,(\d{4}) 可捕获年份,如 2023
  2. 复用模式:如 (\w+)\s\1 匹配重复的单词,如 "test test"。

案例
提取日期中的年、月、日:

(\d{4})-(\d{2})-(\d{2})

高级技巧:前瞻与后顾

前瞻(Lookahead)

前瞻允许检查匹配后的文本,但不将其包含在结果中:

  • 正向前瞻a(?=b) 匹配后面跟着 ba,例如 cab 中的 a
  • 负向前瞻a(?!b) 匹配后面不跟 ba,例如 cat 中的 a

案例
匹配不以 .com 结尾的邮箱:

^[^@]+\@[^@]+\.(?!com$)[a-z]+$

后顾(Lookbehind)

与前瞻类似,但检查匹配前的文本:

  • 正向后顾(?<=a)b 匹配前面是 ab
  • 负向后顾(?<!a)b 匹配前面不是 ab

案例
匹配 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, "");

工具与调试建议

推荐工具

  1. Regex101:实时测试正则表达式,支持高亮匹配和解释模式。
  2. VS Code 内置搜索:通过 /正则表达式/ 格式进行文件查找替换。

调试技巧

  • 逐步简化:从简单模式开始,逐步添加复杂条件。
  • 使用 x 标志(如 /pattern/x):允许在正则中添加空格和注释。
  • 测试边界条件:例如,验证 0、空字符串或特殊符号是否符合预期。

结论与学习建议

总结

正则表达式是文本处理领域的核心工具,其威力在于通过符号组合实现复杂逻辑。从基础的字符匹配到高级的前瞻后顾,掌握正则表达式需要:

  1. 理解元字符的含义:如 .*() 的作用。
  2. 通过案例实践:从邮箱验证、文本提取到数据清洗,实战是提升的关键。
  3. 善用工具辅助:Regex101 等工具能显著降低调试成本。

学习路径建议

  • 初级阶段:学习基础语法和常见模式(如邮箱、电话号码)。
  • 中级阶段:掌握分组、前瞻后顾及替换功能。
  • 高级阶段:探索 Unicode 支持、性能优化和跨语言差异(如 JavaScript 与 Python 的语法差异)。

结语

正则表达式 – 教程的完成,不仅是技术的掌握,更是思维模式的转变。它教会我们如何将模糊的需求转化为精确的逻辑规则,如同在文本的迷宫中铺设一条条清晰的路径。从今天起,不妨尝试用正则表达式解决一个实际问题,你可能会发现:那些曾让你头疼的文本处理任务,原来可以如此优雅而高效!

(字数:约 1800 字)

最新发布