正则表达式 – 语法(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 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)如同一把“万能钥匙”,能够精准匹配、提取、替换文本中的复杂模式。无论是验证用户输入、解析日志文件,还是自动化文本处理,掌握正则表达式 – 语法的核心规则,都能大幅提升开发效率。本文将从零开始,以循序渐进的方式解析正则表达式的基础语法、核心元字符、高级技巧,并通过实际案例演示其应用场景。
正则表达式基础语法:构建模式的“积木”
1. 字符匹配:最基础的“乐高积木”
正则表达式的核心是通过字符组合定义匹配规则。例如,要匹配字符串中的“apple”,可以直接写成 apple
。但若希望匹配“Apple”或“APPLE”,则需要引入元字符(如 i
修饰符)实现不区分大小写。
示例代码(Python):
import re
pattern = r"apple"
text = "Apple is a fruit."
match = re.search(pattern, text, re.IGNORECASE) # 添加 IGNORECASE 修饰符
print(match.group()) # 输出 "Apple"
2. 量词:控制匹配的“次数”
量词用于定义字符或模式的重复次数,常见的包括:
*
:匹配前一个字符 零次或多次+
:匹配前一个字符 一次或多次?
:匹配前一个字符 零次或一次{n}
:精确匹配 n次
比喻:
想象量词如同“倍数放大器”,例如 a+
可以匹配“a”、“aa”甚至“aaaaa”,但不会匹配空字符串。
案例:匹配邮箱域名的后缀
\.com$ # 匹配以 ".com" 结尾的字符串
3. 字符集:定义可选字符的“集合”
用方括号 []
定义一组可选字符,例如 [abc]
可匹配“a”、“b”或“c”。
- 否定字符集:
[^abc]
匹配 非a、b、c 的任意字符。 - 范围简写:
[A-Z]
表示匹配所有大写字母。
示例:匹配中文手机号(11位,以1开头)
^1[3-9]\d{9}$ # ^表示开头,$表示结尾
元字符与特殊符号:正则表达式的核心工具箱
1. 常见元字符及其作用
以下表格总结了正则表达式中常用的元字符及其含义,表格前后保留空行:
元字符 | 含义 | 示例 |
---|---|---|
. | 匹配除换行符外的 任意单个字符 | a.c 可匹配 "abc"、"aZc" |
^ | 匹配字符串的 开头 | ^Hello 匹配以 "Hello" 开头的字符串 |
$ | 匹配字符串的 结尾 | world$ 匹配以 "world" 结尾的字符串 |
| | 逻辑或,匹配两个选项中的一个 | cat|dog 匹配 "cat" 或 "dog" |
\b | 单词边界,匹配单词的开始或结束位置 | \bthe 匹配单词 "the" 的开头 |
2. 转义字符:特殊符号的“安全通道”
若需匹配元字符本身(如 .
或 *
),需用反斜杠 \
进行转义。例如,匹配字符串中的句号应写成 \.
。
注意:
在某些编程语言(如 Python)中,字符串需用双反斜杠 \\
,因为反斜杠本身会被转义。
案例:匹配精确的 IP 地址格式
^(\d{1,3}\.){3}\d{1,3}$ # 匹配类似 "192.168.0.1" 的格式
分组、捕获与引用:组合模式的“粘合剂”
1. 捕获组:临时存储匹配结果
用圆括号 ()
定义捕获组,可将匹配结果存储为变量,供后续引用或处理。例如:
(\d+)-(\d+) # 匹配类似 "123-456" 的字符串,分组存储数字部分
在 Python 中,可通过 groups()
方法获取分组内容:
import re
pattern = r"(\d+)-(\d+)"
text = "ID: 123-456"
match = re.search(pattern, text)
print(match.groups()) # 输出 ("123", "456")
2. 非捕获组:仅分组不存储
若仅需分组但不需要保存结果,可用 ?:
标记:
(?:https?://) # 匹配 "http://" 或 "https://",但不存储结果
3. 反向引用:重复使用捕获组内容
通过 \n
(n为组编号)引用之前捕获的内容。例如,验证邮箱时确保域名前后一致:
^(\w+)@(\w+)\.\2$ # \2 表示引用第二个分组(如 "example.com")
边界与锚点:精准定位的“坐标系”
1. 锚点:锁定匹配的起始与结束
^
和$
分别匹配字符串的 开头和结尾,适用于严格限定格式。- 多行模式:在
^
和$
前加m
修饰符,可匹配每行的开头和结尾。
案例:提取每行的 URL(多行模式)
^https?://\S+ # 在 re.MULTILINE 模式下匹配每行的 URL
2. 词边界 \b
:区分单词的“分界线”
\b
匹配单词边界(如字母与非字母字符的交界处),避免误匹配子字符串。例如:
\bcat\b # 匹配独立单词 "cat",但不匹配 "category"
高级语法与技巧:进阶用户的“工具包”
1. 预查与后顾:条件判断的“望远镜”
- 正向预查
(?=...)
:匹配当前位置后跟随的模式,但不消耗字符。 - 反向预查
(?<!...)
:确保当前位置前不匹配指定模式。
案例:匹配不含敏感词的邮箱
^(?!.*@example\.com\b).*$ # 排除 "@example.com" 的邮箱
2. 非贪婪匹配:最小化匹配的“收缩策略”
默认量词(如 .*
)是“贪婪”的,会尽可能多匹配字符。添加 ?
可变为非贪婪模式:
<a>.*?</a> # 匹配 "<a>text</a>",而非跨标签的长文本
3. 修饰符:全局配置的“快捷键”
i
:忽略大小写g
:全局匹配(在某些语言中为默认)s
:允许.
匹配换行符
示例:忽略大小写的邮箱匹配
/[a-z0-9]+@[a-z]+\.(com|net)/i # i修饰符使匹配不区分大小写
常见应用场景与案例
1. 验证密码强度
要求:8-20位,包含大小写字母、数字和符号。
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,20}$
2. 提取 HTML 标签内的文本
<img\s+src="([^"]+)".*?> # 匹配图片标签中的 src 属性值
3. 格式化电话号码
将输入的任意格式(如 "13812345678" 或 "+86 138-1234-5678")转为 "13812345678":
^\D*(\d{11})\D*$ # 提取连续11位数字
结论
正则表达式 – 语法的学习如同掌握一门“文本处理语言”,其核心在于理解元字符的组合逻辑与边界条件。从基础的字符匹配到高级的预查技巧,每一层知识都能为开发者解锁更复杂的问题解决能力。建议读者通过实际编写案例(如验证表单、解析日志)逐步巩固技能,并参考官方文档(如 Python re
模块或 JavaScript RegExp
)深入探索进阶功能。记住,正则表达式并非万能,合理结合编程逻辑才能发挥其最大价值。
(全文约 2200 字,覆盖基础到进阶知识点,结合代码示例与实际场景,符合 SEO 优化要求。)