Skip to content

正则表达式完全教程

Written/Drawn by claude-opus-4.7

1. 它到底是什么?

「正则表达式」是一种用一小段「模式」去描述一类文本的写法

举个对比:

  • 普通查找:你输入 apple,它去找文本里那一串字符。
  • 正则查找:你输入 \d+,它会找出文本里所有连续的数字——可能是 42、也可能是 1024,长度不限。

你可以把它理解为「带通配规则的查找」,并且这种查找:

  • 能找出很多位置;
  • 能找出结构(比如「日期」「邮箱」「URL」);
  • 能配合替换,做批量改写
正则表达式工作原理:模式 + 输入文本 → 匹配内容搜索:\d+输入:订单 1024,花费 30匹配:102430

2. 第一个例子

直接看一个完整的「查找 + 替换」例子。

项目内容
输入文本今天是 2026-05-17
搜索(正则)\d{4}-\d{2}-\d{2}
匹配到2026-05-17
替换为〔已隐藏日期〕
替换后今天是 〔已隐藏日期〕

只要你能看懂这一步,本教程前 80% 就一半学会了。下面把每个符号慢慢讲清楚。


3. 基础语法

3.1 字面量匹配

最简单的正则,就是「自己」。

字面量直接匹配同样的字符串搜索:hello输入:say hello to me

绝大多数普通字符(字母、数字、汉字)写出来就代表它字面上的样子。 只有少数符号有特殊含义,它们叫元字符

. * + ? ^ $ | \ ( ) [ ] { }

要匹配它们本身,需要在前面加 \ 转义(见 3.9)。


3.2 通配符 .

. 表示「任意一个字符」(默认不含换行符)。

c.t 匹配 cat / cot / cut / c@t,但不匹配 4 字符的 coat搜索:c.t输入:cat cot cut c@t coat说明:「.」只匹配「正好 1 个」字符,因此 4 个字符的 coat 不被匹配。

要点:

  • . 一次只代表 1 个字符;
  • 想匹配字面的「点」要写 \.

3.3 字符类 [ ] 与否定 [^ ]

用方括号列出一个候选清单,匹配里面的任意一个字符。在最前面加 ^ 就表示「不是这些字符」。

字符类:[aeiou]、[0-9]+、[^0-9]+ 三种典型用法搜索:[aeiou]输入:Hello World搜索:[0-9]+输入:电话 138-1234-5678搜索:[^0-9]+输入:ab1cd23ef

支持「范围」简写:

写法含义
[0-9]任意数字
[a-z]任意小写字母
[A-Z]任意大写字母
[a-zA-Z0-9_]字母、数字、下划线

[ ] 里,大部分元字符(. * + 等)都会失去特殊含义,写出来就是字面意义。需要小心的只有 ] \ ^ -


3.4 预定义字符类 \d \w \s

为了不每次都写 [0-9],正则提供了一组「缩写」:

缩写等价于含义
\d[0-9]数字
\D[^0-9]非数字
\w[A-Za-z0-9_]单词字符
\W[^A-Za-z0-9_]非单词字符
\s空白字符空格、Tab、换行等
\S非空白字符

记忆口诀:大写 = 「非」

可以用 [\s\S] 代表任意字符(相当于一个集合加上它的非集等于全集)。


3.5 量词 * + ? {n,m}

量词写在「某个东西」后面,表示这个东西出现几次

?、+、{n} 三种典型量词演示搜索:colou?r输入:colorcolour搜索:\d+输入:编号 42、版本 v3、批次 999搜索:\d{4}输入:卡号 1234 5678 9012
写法含义例子匹配
?0 次 或 1 次colou?rcolorcolour
*0 次 或 更多a*空串、aaa、…
+1 次 或 更多\d+421024
{n}恰好 n 次\d{4}2026
{n,}至少 n 次\d{2,}12123、…
{n,m}n 到 m 次\d{2,4}121231234

记忆口诀:? = 可有可无;+ = 至少一个;* = 来不来都行


3.6 锚点 ^$

它们不匹配任何字符,只表示「位置」:^ = 开头,$ = 结尾。

^Hello 只匹配在开头;end$ 只匹配在结尾搜索:^Hello输入:Hello world✓ 在开头,匹配输入:say Hello✗ 不在开头,不匹配搜索:end$输入:the end✓ 在结尾,匹配说明:^ 和 $ 是「位置」而非「字符」,本身不占长度。

^abc$ 就表示「整段必须正好等于 abc」。


3.7 单词边界 \b

\b 也是一个位置:在「单词字符」和「非单词字符」之间的那条缝。

\bcat\b 只匹配独立的 cat 单词搜索:\bcat\b输入:a cat, the cathedral, scatter说明:cathedral / scatter 里的 cat 不是独立单词,\b 拒绝匹配。

用它可以避免「子串误伤」。


3.8 选择

竖线 | 表示「」,匹配几种可能中的任意一种。

cat|dog|bird 匹配三选一搜索:cat|dog|bird输入:I have a cat and a bird.

也可以配合分组限定范围,比如 gr(a\|e)y 表示 graygrey


3.9 转义 \

把元字符变回普通字符,就在它前面加 \

想匹配写法
.\.
*\*
(\(
\\\
|\|

4. 分组与捕获

4.1 普通捕获组 ( )

圆括号有两个作用:

  1. 分组:让里面的内容作为一个整体接受量词、选择等操作;
  2. 捕获:记录下匹配到的文本,之后可以引用(用于替换、反向引用)。

捕获组从左到右,按 ( 的出现顺序编号:第 1 个是 $1、第 2 个是 $2,依此类推;$0 表示整体匹配

(\d{4})-(\d{2})-(\d{2}) 捕获 $0~$3 四部分搜索:(\d{4})-(\d{2})-(\d{2})输入:2026-05-17捕获:$0= 2026-05-17整体匹配$1= 2026第 1 个括号$2= 05第 2 个括号$3= 17第 3 个括号

4.2 非捕获组 (?: )

如果你只想「分组」不想「捕获」(不占编号、避免编号错位、稍微更快),用 (?:...)

(?:https?):// 匹配 http://https://,但 https/http 这一组不进编号


4.4 反向引用

同一个正则里再次引用前面捕获到的内容,用 \1\2

(\w)\1 找出 oo / ee 等重复字符搜索:(\w)\1输入:look, see, book说明:\1 = 「和第 1 组捕到的字符一模一样」,用来找重复字。

\1 的意思是「和第 1 组捕获到的字符一模一样」——非常适合查重复字、重复词。 命名版本:\k<name>


5. 替换

正则的另一半威力,是替换。绝大多数编辑器、聊天工具、本项目的「正则库」功能都用同一套写法。

5.1 基础替换

如果替换字符串里没有特殊符号,它就照原样写入。

基础替换:把「苹果」换成「apple」搜索:苹果替换为:apple输入:我喜欢苹果和香蕉结果:我喜欢apple和香蕉

5.2 引用整体匹配 $0

$0 代表「这一次匹配到的全部内容」。

用 [$0] 给所有数字加方括号搜索:\d+替换为:[$0]输入:苹果 25 元,香蕉 30结果:苹果 [25] 元,香蕉 [30] 元说明:$0 代表「这一次的整体匹配」。

部分工具也支持 $& 作为 $0 的别名。


5.3 引用捕获组 $1$9

最常用的能力:重新组装文本。

把 2026-05-17 重组为 17/05/2026搜索:(\d{4})-(\d{2})-(\d{2})替换为:$3/$2/$1输入:2026-05-17结果:17/05/2026提示:$0 整体、$1~$9 第 N 个括号;可重复使用、可混入字面文字。

也可以重复使用、可以混入字面文本:

用 $1 $2 把邮箱拆开重组成一句话搜索:(\w+)@(\w+)替换为:用户 $1 来自 $2输入:alice@example结果:用户 alice 来自 example

如果要写字面$,使用 $$:例如「金额 $$$1」会得到「金额 $42」。


5.5 在开头/结尾插入

^$ 本身不消费任何字符,但它们是真实的位置——所以可以「替换」它们,效果就是「在那个位置插入文本」。

用 ^ 在开头插入「> 」;用 $ 在结尾追加「。」搜索:^替换为:> 输入:Hello world结果:> Hello world搜索:$替换为:输入:今天天气真好结果:今天天气真好

5.6 综合替换案例

目的搜索替换为
全角逗号换半角并加空格,
给中文数字加注释([一二三四五六七八九十]+)$1(中文数字)
删除 Markdown 链接外壳\[([^\]]+)\]\([^)]+\)$1
key=value 改 JSON 键值对(\w+)=(\w+)"$1": "$2"

6. 贪婪 vs 懒惰

量词默认是「贪婪」的:能多吃就多吃。在量词后加一个 ?,它就变成「懒惰」:够用就停

同样的 .+,贪婪一次吃完,懒惰只吃一点贪婪:<.+>输入:<b>你好</b>整段被当作一个匹配懒惰:<.+?>输入:<b>你好</b>分成两个独立匹配在任意量词后加一个「?」即可切换:*? +? ?? {n,m}?

懒惰量词:*?+???{n,m}?

经验法则:「找夹在两个东西中间的东西」时,几乎总是用懒惰


7. 进阶:断言

断言(assertion)= 「检查上下文,但不消费字符」。它本身不进入匹配结果,只用来约束「这个位置周围必须长什么样」。

先行断言与后行断言示意搜索:\d+(?=元)输入:苹果 25元,西瓜 30kg说明:先行断言 (?=...) — 右边必须满足,但「元」本身不进入结果。搜索:(?<=\$)\d+输入:价格 $30,折后 100说明:后行断言 (?<=...) — 左边必须满足,但「$」本身不进入结果。
写法名称含义
(?=...)先行断言右边必须满足 ...
(?!...)否定先行断言右边必须满足 ...
(?<=...)后行断言左边必须满足 ...
(?<!...)否定后行断言左边必须满足 ...

常见场景:

  • 「找出价格但不要单位」\d+(?=元\|¥\|RMB)
  • 「找出后面是冒号的单词」\w+(?=:)
  • 「找出前面不是 $ 的数字」(?<!\$)\d+

8. 两个常用开关

不同工具的「正则设置」面板里,最常见的就这两个开关——其他的几乎用不到:

开关关闭时(默认)打开时
区分大小写Hello 不匹配 helloHello 也可以匹配 helloHELLO
全局匹配只处理第一个匹配处理所有匹配(替换时尤其重要)

替换功能几乎总是要打开「全局匹配」,否则只换一处。


9. 速查表

9.1 元字符

符号含义
.任意单字符(默认不含换行)
^开头
$结尾
|
\转义下一个字符
( )分组 + 捕获
[ ]字符类
{ }量词次数

9.2 字符类

写法含义
[abc]a 或 b 或 c
[^abc]不是 a/b/c
[a-z]a 到 z 任一字符
\d数字 = [0-9]
\D非数字
\w单词字符 = [A-Za-z0-9_]
\W非单词字符
\s空白
\S非空白
\n \t \r换行/制表/回车

9.3 量词

写法含义
?0 或 1
*0 或更多
+1 或更多
{n}恰好 n
{n,}至少 n
{n,m}n 到 m
量词?切换为懒惰

9.4 锚点与边界

写法含义
^字符串开头
$字符串结尾
\b单词边界
\B非单词边界

9.5 分组与引用

写法含义
(...)捕获组
(?:...)非捕获组
(?<name>...)命名捕获组
\1 \2反向引用(在正则内)
\k<name>命名反向引用

9.6 断言

写法含义
(?=...)右边必须是 ...
(?!...)右边必须不是 ...
(?<=...)左边必须是 ...
(?<!...)左边必须不是 ...

9.7 替换字符串语法

写法含义
$0整体匹配
$1$9第 N 个捕获组
${name}命名捕获组
$$字面 $
其他文本照原样写入

10. 实战案例集

隐藏手机号中间四位

(\d{3})\d{4}(\d{4}) → $1****$2搜索:(\d{3})\d{4}(\d{4})替换为:$1****$2输入:13812345678结果:138****5678

给数字加千位分隔

用先行断言实现千位分隔:1234567 → 1,234,567搜索:(\d)(?=(\d{3})+(?!\d))替换为:$1,输入:1234567结果:1,234,567

含义:在某个数字右边,正好有若干组 3 位数字,并且再往右不是数字——这样的位置就插一个逗号。

更多速用配方

目的搜索替换为
提取所有 URLhttps?://\S+
校验邮箱(够用版)^[\w.+-]+@[\w-]+(\.[\w-]+)+$
提取中文文本[一-鿿]+
合并多个空行\n{3,}\n\n
2026/05/172026-05-17(\d{4})/(\d{2})/(\d{2})$1-$2-$3
提取 Markdown 标题文字^#+\s*(.+?)\s*$$1
删除所有 HTML 标签<[^>]+>(空)
**粗体**__粗体__\*\*([^*]+)\*\*__$1__

到这里你已经掌握了正则的全部核心能力——剩下的就是练习。 建议挑一个上面的案例,自己改输入文本,观察匹配/替换结果,几次之后就会形成肌肉记忆。

11. 更多资源

本教程及配图由AI编写,如果你想要学习其它教程,推荐前往 菜鸟教程 或直接搜索 正则表达式 教程 阅读更多进阶教程