从入门到实战的正则表达式使用教程。
不同于原理剖析,这聚焦于**"怎么用"**------包括语法速查、各语言的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''可避免。
第五部分:学习路线与调试工具
推荐学习顺序(由易到难)
-
先记9个元字符 + 3个量词(上文第一部分)
-
练手 :用
findall提取数字、邮箱、URL -
学分组捕获:提取匹配中的特定部分
-
学断言 :
(?=...)和(?!...)(检查但不消费字符) -
学优化 :非捕获分组
(?:...)、原子分组(?>...)
必备调试工具
-
Regex101 (regex101.com):最强大,支持多语言、显示匹配步骤和回溯次数
-
RegExr (regexr.com):界面友好,带语法速查
-
Regex Debugger(VSCode插件):在编辑器中实时调试