MagicTools
developerMarch 18, 2026110 views4 min read

正则表达式入门完全指南:10 个实用例子从零学会

第一次看到正则表达式时,很多开发者的第一反应是:"这是什么乱码?"

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$

但当你真正理解正则之后,你会发现:曾经需要写 30 行代码的文本处理,现在一行搞定。表单验证、日志分析、代码重构、数据提取——正则表达式无处不在。

本文用最直观的方式带你入门,并给出 10 个直接可以复制使用的实战正则。


基础语法快速上手

字符类

语法 含义 示例
. 任意单个字符(除换行符) a.c 匹配 abca1c
\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 匹配 acabcabbc
+ 1 个或多个 ab+c 匹配 abcabbc,不匹配 ac
? 0 个或 1 个(可选) colou?r 匹配 colorcolour
{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 的数字(25[0-5] 匹配 250255,2[0-4]\d 匹配 200249,[01]?\d\d? 匹配 0199)。


不同语言中正则的差异

特性 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:有没有办法让正则更可读?

有两种方式:

  1. 注释模式(Verbose Mode):Python 中用 re.VERBOSE 标志,允许在正则中添加空格和注释
  2. 拆分为多个变量:把复杂正则拆分为几个有意义的片段,再用字符串拼接
# 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 类场景遇到嵌套结构别强求正则,用专业解析器。正则是利器,但不是万能钥匙。

Published by MagicTools