正则表达式的使用教程

从入门到实战的正则表达式使用教程。

不同于原理剖析,这聚焦于**"怎么用"**------包括语法速查、各语言的API用法、以及最常见的实战场景。

尽量让教程即查即用,可以把它当作一份随时翻阅的手册。


第一部分:核心语法速查表

1. 元字符速记(最常用的9个)

元字符 含义 等价于
. 任意单个字符(除换行符) -
\d 数字0-9 [0-9]
\D 非数字 [^0-9]
\w 单词字符(字母、数字、下划线) [a-zA-Z0-9_]
\W 非单词字符 [^a-zA-Z0-9_]
\s 空白字符(空格、Tab、换行等) [ \t\r\n\f]
\S 非空白字符 [^ \t\r\n\f]
\b 单词边界(位置,不占字符) -
^ $ 字符串开头/结尾(多行模式下为行首/行尾) -

2. 量词(控制重复次数)

量词 含义 贪婪/非贪婪
* 0次或多次 贪婪(尽可能多)
+ 1次或多次 贪婪
? 0次或1次 贪婪
{n} 恰好n次 贪婪
{n,} 至少n次 贪婪
{n,m} n到m次 贪婪
*? +? ?? {n,m}? 对应非贪婪版本 懒惰(尽可能少)

记忆口诀* 像"星星眨眼"(可有可无),+ 像"加号"(至少一个),? 像"问号"(有或没有)。

3. 字符类(自定义匹配范围)

  • [abc]:匹配a、b或c中的一个字符

  • [^abc]:匹配除a、b、c之外的任意字符(取反

  • [a-z]:匹配a到z的任意小写字母

  • [a-zA-Z0-9]:匹配大小写字母和数字(同 \w

4. 分组与捕获

语法 作用
(pattern) 捕获分组,匹配后可通过 \1$1 引用
(?:pattern) 非捕获分组,只用于分组但不保存(性能更好)
(?<name>pattern) 命名分组(Python/JS等支持)
\1 \2 反向引用,匹配前面第1/2个捕获组的内容

第二部分:各语言中的用法(附代码片段)

Python(使用 re 模块)

python 复制代码
import re

text = "我的手机号是13812345678,邮箱是test@example.com"

# 1. search() - 查找第一个匹配
phone = re.search(r'1[3-9]\d{9}', text)
print(phone.group())  # 13812345678

# 2. findall() - 返回所有匹配的列表
emails = re.findall(r'\w+@\w+\.\w+', text)
print(emails)  # ['test@example.com']

# 3. finditer() - 返回迭代器(适合大文本,节省内存)
for match in re.finditer(r'\d+', text):
    print(match.group(), match.span())

# 4. sub() - 替换
new_text = re.sub(r'1[3-9]\d{9}', '****', text)
print(new_text)  # 我的手机号是****,邮箱是test@example.com

# 5. split() - 按正则切分
parts = re.split(r'[,,、]', "苹果,香蕉,橙子")
print(parts)  # ['苹果', '香蕉', '橙子']

# 6. 预编译(性能优化,循环中使用)
pattern = re.compile(r'\d{4}-\d{2}-\d{2}')  # 日期格式
result = pattern.search("今天是2026-07-02")

JavaScript

javascript 复制代码
const text = "我的手机号是13812345678";

// 1. test() - 是否匹配(返回布尔)
const hasPhone = /1[3-9]\d{9}/.test(text);  // true

// 2. exec() - 执行匹配(返回数组或null)
const match = /1([3-9])\d{9}/.exec(text);
console.log(match[1]);  // '8'(第一个捕获组)

// 3. match() - 字符串方法
const phones = text.match(/1[3-9]\d{9}/g);  // g表示全局匹配
console.log(phones);  // ['13812345678']

// 4. replace() - 替换
const masked = text.replace(/1[3-9]\d{9}/, '****');
console.log(masked);  // 我的手机号是****

// 5. 命名分组(ES2018+)
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const result = re.exec('2026-07-02');
console.log(result.groups.year);  // '2026'

Java(使用 java.util.regex

java 复制代码
import java.util.regex.*;

String text = "手机号: 13812345678";

// 1. 基本用法
Pattern p = Pattern.compile("1[3-9]\\d{9}");  // 注意双重转义
Matcher m = p.matcher(text);

if (m.find()) {
    System.out.println(m.group());  // 13812345678
}

// 2. 全局查找
while (m.find()) {
    System.out.println("找到: " + m.group() + ",位置: " + m.start());
}

// 3. 替换
String replaced = text.replaceAll("1[3-9]\\d{9}", "****");

命令行(grep/sed/awk)

bash 复制代码
# grep - 查找匹配行
grep -E "1[3-9][0-9]{9}" access.log

# sed - 替换
sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2}/日期/g' file.txt

# awk - 提取字段
awk '/(\d{4})-(\d{2})-(\d{2})/{print $0}' file.txt

第三部分:15个实战高频场景

1. 手机号(中国大陆)

复制代码
^1[3-9]\d{9}$

2. 邮箱(标准版)

复制代码
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

3. 身份证号(18位)

复制代码
^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$

4. IPv4地址

复制代码
^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$

5. 日期(YYYY-MM-DD)

复制代码
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

6. URL

复制代码
^https?://[^\s/$.?#].[^\s]*$

7. 提取所有中文字符

复制代码
[\u4e00-\u9fa5]+

8. 删除HTML标签

复制代码
<[^>]*>

9. 匹配空行

复制代码
^\s*$

10. 匹配强密码(至少8位,含大小写字母和数字)

复制代码
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$

(?=...)正向先行断言,用于检查是否包含某字符,但不消耗字符。

11. 提取日志中的时间戳

复制代码
\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}

12. 匹配文件扩展名

复制代码
\.(jpg|jpeg|png|gif|webp)$

13. 匹配中文姓名(2-4个汉字)

复制代码
^[\u4e00-\u9fa5]{2,4}$

14. 匹配QQ号(5-11位数字,不以0开头)

复制代码
^[1-9]\d{4,10}$

15. 匹配16进制颜色

复制代码
^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$

第四部分:常见的3个坑及避坑指南

坑1:. 不匹配换行符

  • 现象<p>.*</p> 无法匹配跨多行的内容。

  • 解决 :Python用 re.DOTALL,JS用 [\s\S]* 替代 .*

复制代码
# Python
re.search(r'<p>.*</p>', html, re.DOTALL)

# JavaScript
/<p>[\s\S]*<\/p>/

坑2:贪婪导致匹配结果比预期多

  • 现象<.*> 匹配 <div>test</div><p>hi</p> 会整个一起匹配。

  • 解决 :改用非贪婪 .*? 或取反字符类 [^>]*

复制代码
# 方案1(非贪婪)
<.*?>
# 方案2(更推荐)
<[^>]*>

坑3:正则中的反斜杠需要双重转义

  • 现象 :Java中写 \d 要写成 \\d,因为字符串本身会先转义一次。

  • 解决 :Java、C#等语言注意转义;Python用原始字符串 r'' 可避免。


第五部分:学习路线与调试工具

推荐学习顺序(由易到难)

  1. 先记9个元字符 + 3个量词(上文第一部分)

  2. 练手 :用 findall 提取数字、邮箱、URL

  3. 学分组捕获:提取匹配中的特定部分

  4. 学断言(?=...)(?!...)(检查但不消费字符)

  5. 学优化 :非捕获分组 (?:...)、原子分组 (?>...)

必备调试工具

  • Regex101regex101.com):最强大,支持多语言、显示匹配步骤和回溯次数

  • RegExrregexr.com):界面友好,带语法速查

  • Regex Debugger(VSCode插件):在编辑器中实时调试

相关推荐
大郭鹏宇2 小时前
MongoDB快速实战与基本原理入门
数据库·mongodb
KASH_SHADOW2 小时前
8-Mysql的安装与配置
数据库·mysql·adb
澈2072 小时前
【无标题】QT入门第十二天:数据库编程(下)模型视图与数据展示 | 零基础学QT
数据库·qt·oracle
SeeYa-J2 小时前
Sprint 1-2:创建第一个 Spring Boot Module(user-service)
java·spring boot·sprint
云絮.2 小时前
数据库事务
java·开发语言·数据库
格子软件2 小时前
2026年GEO优化系统源码级状态机与多模型调度拆解
java·前端·vue.js·人工智能·vue·geo
Full Stack Developme3 小时前
Java 漏斗算法 及应用场景
java·开发语言·算法
从此以后自律3 小时前
Spring 全家桶
java·后端·spring