正则表达式 – 语法(长文讲解)

更新时间:

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

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 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 优化要求。)

最新发布