正则表达式入门完全指南:10 个实用例子从零学会
第一次看到正则表达式时,很多开发者的第一反应是:"这是什么乱码?"
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$
但当你真正理解正则之后,你会发现:曾经需要写 30 行代码的文本处理,现在一行搞定。表单验证、日志分析、代码重构、数据提取——正则表达式无处不在。
本文用最直观的方式带你入门,并给出 10 个直接可以复制使用的实战正则。
基础语法快速上手
字符类
| 语法 | 含义 | 示例 |
|---|---|---|
. |
任意单个字符(除换行符) | a.c 匹配 abc、a1c |
\d |
数字,等同于 [0-9] |
\d\d 匹配 42 |
\D |
非数字 | \D+ 匹配 abc |
\w |
字母/数字/下划线,等同于 [a-zA-Z0-9_] |
\w+ 匹配 hello_world |
\W |
非单词字符 | \W 匹配空格、标点 |
\s |
空白字符(空格、Tab、换行) | \s+ 匹配连续空格 |
[abc] |
字符集合,匹配 a、b 或 c | [aeiou] 匹配元音 |
[^abc] |
否定字符集,不匹配 a、b、c | [^0-9] 匹配非数字 |
[a-z] |
字符范围,匹配 a 到 z | [A-Za-z] 匹配所有字母 |
量词
| 语法 | 含义 | 示例 |
|---|---|---|
* |
0 个或多个 | ab*c 匹配 ac、abc、abbc |
+ |
1 个或多个 | ab+c 匹配 abc、abbc,不匹配 ac |
? |
0 个或 1 个(可选) | colou?r 匹配 color 和 colour |
{n} |
恰好 n 个 | \d{4} 匹配 4 位数字 |
{n,m} |
n 到 m 个 | \d{6,8} 匹配 6~8 位数字 |
{n,} |
至少 n 个 | \d{3,} 匹配 3 位及以上数字 |
锚点
| 语法 | 含义 |
|---|---|
^ |
字符串开头 |
$ |
字符串结尾 |
\b |
单词边界(单词与非单词的交界处) |
分组与捕获
| 语法 | 含义 |
|---|---|
(...) |
捕获组,可通过 $1、\1 反向引用 |
(?:...) |
非捕获组,仅分组不捕获 |
(?P<name>...) |
命名捕获组(Python/PCRE 语法) |
(?<name>...) |
命名捕获组(JavaScript ES2018+ 语法) |
其他
| 语法 | 含义 |
|---|---|
a|b |
或:匹配 a 或 b |
\ |
转义字符,\. 匹配字面量点号 |
(?=...) |
正向前瞻(后面必须跟着...) |
(?!...) |
负向前瞻(后面不能跟着...) |
10 个实用正则表达式
1. 验证邮箱地址
^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$
说明:本地部分允许字母、数字和 ._%+-,@ 后为域名,顶级域名至少 2 个字母。
// JavaScript 示例
const emailRegex = /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/;
emailRegex.test('user@example.com'); // true
emailRegex.test('invalid.email'); // false
emailRegex.test('a@b.c'); // false(TLD 太短)
2. 验证中国手机号(11位)
^1[3-9]\d{9}$
说明:中国手机号以 1 开头,第二位为 3~9,后跟 9 位数字,共 11 位。
# Python 示例
import re
pattern = re.compile(r'^1[3-9]\d{9}$')
pattern.match('13812345678') # 匹配
pattern.match('12345678901') # 不匹配(第二位为2)
3. 验证 URL
^https?:\/\/([\w\-]+\.)+[\w\-]+(\/[\w\-._~:/?#\[\]@!$&'()*+,;=%]*)?$
说明:匹配 http:// 或 https:// 开头的 URL,支持路径、查询参数和锚点。
4. 提取 HTML 标签内容
<(\w+)[^>]*>(.*?)<\/\1>
说明:捕获组 \1 反向引用,确保开闭标签一致。.*? 是懒惰匹配,避免跨标签贪婪。
const html = '<p class="intro">Hello World</p>';
const match = html.match(/<(\w+)[^>]*>(.*?)<\/\1>/);
console.log(match[1]); // "p"(标签名)
console.log(match[2]); // "Hello World"(内容)
⚠️ 注意:正则不能解析嵌套 HTML,生产环境请使用 DOM 解析器。
5. 替换多个连续空格为单个空格
\s+
const str = ' Hello World ';
const cleaned = str.trim().replace(/\s+/g, ' ');
// "Hello World"
6. 验证中国居民身份证号(18位)
^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$
说明:6 位地区码 + 4 位年份(19xx/20xx)+ 2 位月份(0112)+ 2 位日期(0131)+ 3 位顺序码 + 1 位校验码(0~9 或 X)。
7. 提取字符串中所有数字
\d+
import re
text = "商品A价格199元,商品B价格1299元"
numbers = re.findall(r'\d+', text)
# ['199', '1299']
8. 验证日期格式(YYYY-MM-DD)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
说明:精确验证月份范围(0112)和日期范围(0131),但不能验证 2 月 30 日这类逻辑错误,日期逻辑验证需配合代码处理。
9. 密码强度验证(至少 8 位,含大小写字母和数字)
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$
说明:
(?=.*[a-z])正向前瞻:必须包含至少一个小写字母(?=.*[A-Z])正向前瞻:必须包含至少一个大写字母(?=.*\d)正向前瞻:必须包含至少一个数字[a-zA-Z\d@$!%*?&]{8,}允许的字符集,总长度至少 8 位
10. 匹配 IPv4 地址
^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$
说明:每段匹配 0255 的数字(255,25[0-5] 匹配 2502[0-4]\d 匹配 200249,199)。[01]?\d\d? 匹配 0
不同语言中正则的差异
| 特性 | JavaScript | Python | Java |
|---|---|---|---|
| 命名捕获组 | (?<name>...) |
(?P<name>...) |
(?<name>...) |
| 字符串方法 | str.match() / str.replace() |
re.match() / re.findall() |
Pattern.compile() |
| 修饰符写法 | /pattern/gi |
re.IGNORECASE |
Pattern.CASE_INSENSITIVE |
| 多行模式 | /pattern/m |
re.MULTILINE |
Pattern.MULTILINE |
| 后行断言 | 支持(V8 引擎) | 支持 | 支持(Java 8+) |
| Unicode 支持 | /pattern/u 标志 |
默认支持 | 需显式指定 |
常见陷阱
贪婪匹配 vs 懒惰匹配
const html = '<b>粗体</b> 和 <b>另一个粗体</b>';
// 贪婪匹配(默认):尽可能多匹配
html.match(/<b>.*<\/b>/)[0];
// '<b>粗体</b> 和 <b>另一个粗体</b>' ← 吞掉了中间内容!
// 懒惰匹配:在量词后加 ?
html.match(/<b>.*?<\/b>/)[0];
// '<b>粗体</b>' ← 正确!
回溯性能问题(ReDoS)
某些正则在特定输入下会发生指数级回溯,导致性能崩溃:
# 危险的正则(嵌套量词)
^(a+)+$
# 对于输入 "aaaaaaaaaaaab",回溯次数呈指数增长
规避原则:避免嵌套量词 (a+)+、(a|a)+,使用 Possessive Quantifiers 或原子组(某些引擎支持)。
FAQ
Q:正则表达式能解析 HTML 吗?
不推荐。HTML 是非正规语言,存在嵌套结构,而正则的有限状态机模型无法处理任意深度的嵌套。解析标签内容、属性等简单场景可以用正则,但完整解析 HTML 文档必须用 DOM 解析器(浏览器的 DOMParser、Python 的 BeautifulSoup、Node.js 的 cheerio 等)。Stack Overflow 上有一篇著名的"不要用正则解析 HTML"的回答,被点赞超过 6000 次——这是行业共识。
Q:如何调试正则表达式?
推荐以下工具:
- regex101.com:功能最强,实时高亮匹配、逐步调试、解释每个语法元素,支持 JavaScript/Python/PHP/Go 等多种语言模式
- regexr.com:界面友好,适合初学者
- debuggex.com:可视化正则的 NFA/DFA 状态机,帮助理解匹配原理
- IDE 内置:VS Code、JetBrains 系 IDE 均支持正则预览
Q:有没有办法让正则更可读?
有两种方式:
- 注释模式(Verbose Mode):Python 中用
re.VERBOSE标志,允许在正则中添加空格和注释 - 拆分为多个变量:把复杂正则拆分为几个有意义的片段,再用字符串拼接
# Python verbose 模式示例
import re
email_pattern = re.compile(r"""
^ # 字符串开头
[a-zA-Z0-9._%+\-]+ # 本地部分
@ # @ 符号
[a-zA-Z0-9.\-]+ # 域名
\. # 点号
[a-zA-Z]{2,} # 顶级域名
$ # 字符串结尾
""", re.VERBOSE)
总结
正则表达式的学习曲线陡峭,但核心语法并不多——掌握字符类、量词、锚点、分组这四大类,就能解决 80% 的实际问题。本文提供的 10 个实用正则可以直接复制使用,遇到新需求时先在 regex101.com 上实验,再集成到代码中。
记住两条原则:用懒惰匹配代替贪婪匹配处理 HTML 类场景;遇到嵌套结构别强求正则,用专业解析器。正则是利器,但不是万能钥匙。