10 分钟学会正则表达式

正则表达式看起来像猫从键盘上踩过,其实只是五个概念挤在紧凑的语法里。理解这五个概念,收藏下面的模式库,再避开贪婪匹配和点号未转义这两个常见陷阱,就够用了。音频只讲思路;需要符号时,请直接看页面。

🎙️ 发布并录制于: · 更新于 ·

01基本模型:描述形状,不是具体文本

正则表达式描述的是文本的形状。比如,三位数字、一个短横线、再来四位数字。引擎会拿着这个描述,从字符串开头一路滑过去,寻找能对上的位置。原理就这么简单。先记住第一条:如果你只是在找一段固定文本,根本不需要正则。用 inincludes() 更快,也不会给你意外。

# 形状:“数字、短横线、数字”——匹配电话号码
\d{3}-\d{4}

"call 555-0199 today"   →  matches  "555-0199"

# 但固定文本不需要正则:
✗ re.search("error", line)     # 小题大做
✓ "error" in line              # 结果相同,也更稳妥

02字符类:这里允许出现什么

字符类回答一个问题:这个位置可以放什么字符?最常用的三个简写分别代表数字、单词字符和空白字符。方括号可以列出允许的范围;在方括号里加脱字符,则表示排除这些字符。

\d    # 一个数字             0-9
\w    # 一个“单词”字符       字母、数字、_
\s    # 一个空白字符         空格、制表符、换行符
.     # 任意一个字符(换行符除外)——小心,见第 07 节

[abc]     # 恰好是 a、b、c 中的一个
[a-f0-9]  # 一个十六进制数字(用 - 表示范围)
[^0-9]    # 一个非数字字符([] 内的 ^ 表示“非”)

\D \W \S  # 大写形式与对应的小写形式含义相反

03量词:要出现多少次

量词放在一个元素的后面,说明它要重复几次。常用情况只有四类:可有可无、任意次数、至少一次,以及用花括号写出的准确次数或范围。

colou?r        # ? = 0 或 1      → color, colour
go+al          # + = 1 次或更多  → goal, gooooal
ab*c           # * = 0 次或更多  → ac, abc, abbbc
\d{4}          # 恰好 4 次       → 2026
\d{2,4}        # 2 到 4 次       → 26, 202, 2026
\d{2,}         # 2 次或更多

# 读法练习——一个简单的日期形状:
\d{4}-\d{2}-\d{2}      # 2026-07-24

04贪婪陷阱:.* 会吞掉一切

这是整页最值得听的一分半钟。量词默认是贪婪的:只要最终还能匹配成功,它就会尽量多拿字符。把这个特性和点号加星号放在一起,就会出现最经典的正则错误:从第一个开头一直吃到最后一个结尾,中间的内容全部被吞进去。

text:  <b>bold</b> and <i>italic</i>

<.*>      # 贪婪:匹配 <b>bold</b> and <i>italic</i>——全部内容!
<.*?>     # 懒惰(加 ?):依次匹配 <b>、</b>、<i>…… ✓
<[^>]*>   # 通常更好:“除结束符外的任意内容”——更快、更明确
经验法则
匹配结果远比预期长,通常就是贪婪量词惹的祸。可以在量词后加 ? 改成懒惰模式;更好的办法通常是把点号换成否定字符类,也就是“除了结束字符之外的任何字符”。这样写更贴近你的真实意图。

05锚点:限定位置,不匹配字符

锚点匹配的是位置,不是字符。它们表示字符串开头、字符串结尾或单词边界。很多隐蔽错误不是模式写错了,而是匹配到了错误的位置。比如只用 \d+ 验证数字时,"abc123abc" 也能通过,因为中间确实有一个一百二十三。

^\d+$     # ^ 是开头,$ 是结尾 → 整个字符串只能是数字
          # 没有锚点时,"abc123abc" 也会通过!(找到了中间的 123)

\bcat\b   # \b = 单词边界 → 匹配单词 "cat",
          #   不匹配 "category" 或 "concatenate" 中的 cat

^ERROR    # 匹配以 ERROR 开头的行(需启用多行标志)
验证规则
凡是用正则验证用户输入,比如金额、ID 或代码是否合法,都必须同时限定开头和结尾。没有锚点时,攻击者的字符串只要包含一小段看似合法的内容,就可能绕过验证。搜索可以不加锚点;验证一定要加。没有例外。

06分组:取出你真正需要的部分

圆括号有两个作用。第一是组合,让量词或“或者”作用于整个片段;第二是捕获,把匹配到的部分交还给代码,并按从左到右的顺序编号。竖线表示“或者”。

# 组合 + 或者:
\.(jpg|png|gif)$          # 匹配以这三种扩展名之一结尾的文件

# 捕获:从日期中取出各个部分
(\d{4})-(\d{2})-(\d{2})
#  └ 第 1 组:年  └ 第 2 组:月  └ 第 3 组:日

# 在 Python 中:
m = re.search(r"(\d{4})-(\d{2})-(\d{2})", text)
m.group(1)                # "2026"

# 用反向引用调换顺序:"Lastname, First" → "First Lastname"
re.sub(r"(\w+), (\w+)", r"\2 \1", "Lovelace, Ada")

07转义陷阱:一个点号匹配得太多

正则里有十五个字符带特殊含义。如果你想按字面使用它们,却忘了加反斜杠,模式就会悄悄匹配更多内容。最典型的是域名和价格里的点号。没有转义的点号,不是句点,而是“任意字符”。

# 特殊字符(按字面匹配时要用 \ 转义):
.  *  +  ?  (  )  [  ]  {  }  ^  $  |  \  /

swiftgrasp.com     # . 会匹配任意字符:
                   #   因此也会匹配 "swiftgraspXcom" ⚠
swiftgrasp\.com    # ✓ 按字面匹配点号

$19.99             # $ 表示“字符串结尾”——永远匹配不到!
\$19\.99           # ✓ 按字面匹配美元符号和点号
为什么这个错误很难被发现
没转义的点号仍然能匹配正确文本。swiftgrasp.com 的确可以匹配 "swiftgrasp.com",所以测试会通过。问题是它还会匹配不该匹配的内容,往往要到生产环境遇到奇怪的边界情况才暴露。正则测试不能只测“应该匹配什么”,还必须断言“绝不能匹配什么”。

08常用模式库:复制、粘贴、再调整

下面是最常用的一组模式,都经过测试,也加了说明。先说清一个著名陷阱:不存在实用的“完美邮箱正则”。邮件规范允许许多怪异写法,生产系统通常只做简单格式检查,再发一封确认邮件。务实比死抠规范更可靠。

# 邮箱(务实版本——配合确认邮件使用)
^[\w.+-]+@[\w-]+\.[\w.]+$

# URL(http/https)
https?://[^\s]+

# ISO 日期  2026-07-24
\b\d{4}-\d{2}-\d{2}\b

# 时间  14:30 或 9:05
\b\d{1,2}:\d{2}\b

# 可带小数的数字(价格、金额)
-?\d+(\.\d+)?

# IPv4(务实版本)
\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b

# 把连续空白压缩成一个空格
\s+        # 替换为 " "

# 提取双引号之间的全部内容
"([^"]*)"

# 十六进制颜色  #fff 或 #1a2b3c
#[0-9a-fA-F]{3,6}\b

09什么时候不该用正则

真正熟练的人,知道什么时候应该拒绝正则。记住三条。固定文本不需要正则。嵌套结构,比如 HTML、JSON 和代码,不能靠正则正确解析,这是能力边界,不是你技巧不够,应该使用真正的解析器。最后,如果模式长到一行放不下,将来的你一定会埋怨现在的你。正则是一把手术刀,不是电锯。

✗ parsing HTML with regex     # 使用 HTML 解析器(BeautifulSoup……)
✗ parsing JSON with regex     # 使用 json.loads——现成而且正确
✗ a 200-char regex            # 拆成多个步骤,或写一个小型解析器

✓ log line extraction         # 这是正则最擅长的场景
✓ validation (anchored!)      # 还要配合负向测试
✓ find & replace in editor    # 每天都能用上的强大工具
能彻底改变体验的工具
不要盯着正则干想。把它粘贴到 regex101.com,那里会解释每个符号、实时显示匹配结果,还能建立测试集。用两分钟实际测试,胜过眯着眼看二十分钟。多数编辑器的查找替换也支持正则,这是很多人一直没打开的日常利器。

10速查表

最后,把整页内容压缩成一张速查表。

# 字符类                      # 量词
\d 数字    [abc] 三选一       ?  0-1        *  0+
\w 单词    [a-z] 范围         +  1+         {n,m} 指定次数
\s 空白    [^x] 不是 x        后加 ? → 懒惰版本

# 锚点                        # 分组
^  开头    $  结尾            (x)  捕获
\b 单词边界                   (a|b) 或者
验证一律使用 ^...$            \1 反向引用

# 两个陷阱
.* 太贪婪   → .*? 或 [^X]*
按字面匹配 . $ + ? → 转义:\. \$ \+ \?

# 调试
regex101.com — 解释、测试、保存

# 该拒绝时就拒绝
固定文本 → in/includes · HTML/JSON → 真正的解析器

到这里,初学开发者需要的技术栈就串起来了:PythonGit命令行SQLHTTPDocker → 正则表达式。七个页面,大约七十分钟音频,足够建立第一年动手做项目所需的基本词汇。现在去做一个东西吧。

Tell me what missed

A correction is more useful than a compliment. This goes straight to the person who writes SwiftGrasp.

Was this page useful?
0/1000

Please do not include passwords, private keys, or personal information.