正则表达式看起来像猫从键盘上踩过,其实只是五个概念挤在紧凑的语法里。理解这五个概念,收藏下面的模式库,再避开贪婪匹配和点号未转义这两个常见陷阱,就够用了。音频只讲思路;需要符号时,请直接看页面。
🎙️ 发布并录制于: · 更新于 ·
正则表达式描述的是文本的形状。比如,三位数字、一个短横线、再来四位数字。引擎会拿着这个描述,从字符串开头一路滑过去,寻找能对上的位置。原理就这么简单。先记住第一条:如果你只是在找一段固定文本,根本不需要正则。用 in 或 includes() 更快,也不会给你意外。
# 形状:“数字、短横线、数字”——匹配电话号码
\d{3}-\d{4}
"call 555-0199 today" → matches "555-0199"
# 但固定文本不需要正则:
✗ re.search("error", line) # 小题大做
✓ "error" in line # 结果相同,也更稳妥字符类回答一个问题:这个位置可以放什么字符?最常用的三个简写分别代表数字、单词字符和空白字符。方括号可以列出允许的范围;在方括号里加脱字符,则表示排除这些字符。
\d # 一个数字 0-9
\w # 一个“单词”字符 字母、数字、_
\s # 一个空白字符 空格、制表符、换行符
. # 任意一个字符(换行符除外)——小心,见第 07 节
[abc] # 恰好是 a、b、c 中的一个
[a-f0-9] # 一个十六进制数字(用 - 表示范围)
[^0-9] # 一个非数字字符([] 内的 ^ 表示“非”)
\D \W \S # 大写形式与对应的小写形式含义相反量词放在一个元素的后面,说明它要重复几次。常用情况只有四类:可有可无、任意次数、至少一次,以及用花括号写出的准确次数或范围。
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这是整页最值得听的一分半钟。量词默认是贪婪的:只要最终还能匹配成功,它就会尽量多拿字符。把这个特性和点号加星号放在一起,就会出现最经典的正则错误:从第一个开头一直吃到最后一个结尾,中间的内容全部被吞进去。
text: <b>bold</b> and <i>italic</i>
<.*> # 贪婪:匹配 <b>bold</b> and <i>italic</i>——全部内容!
<.*?> # 懒惰(加 ?):依次匹配 <b>、</b>、<i>…… ✓
<[^>]*> # 通常更好:“除结束符外的任意内容”——更快、更明确? 改成懒惰模式;更好的办法通常是把点号换成否定字符类,也就是“除了结束字符之外的任何字符”。这样写更贴近你的真实意图。锚点匹配的是位置,不是字符。它们表示字符串开头、字符串结尾或单词边界。很多隐蔽错误不是模式写错了,而是匹配到了错误的位置。比如只用 \d+ 验证数字时,"abc123abc" 也能通过,因为中间确实有一个一百二十三。
^\d+$ # ^ 是开头,$ 是结尾 → 整个字符串只能是数字
# 没有锚点时,"abc123abc" 也会通过!(找到了中间的 123)
\bcat\b # \b = 单词边界 → 匹配单词 "cat",
# 不匹配 "category" 或 "concatenate" 中的 cat
^ERROR # 匹配以 ERROR 开头的行(需启用多行标志)圆括号有两个作用。第一是组合,让量词或“或者”作用于整个片段;第二是捕获,把匹配到的部分交还给代码,并按从左到右的顺序编号。竖线表示“或者”。
# 组合 + 或者:
\.(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")正则里有十五个字符带特殊含义。如果你想按字面使用它们,却忘了加反斜杠,模式就会悄悄匹配更多内容。最典型的是域名和价格里的点号。没有转义的点号,不是句点,而是“任意字符”。
# 特殊字符(按字面匹配时要用 \ 转义):
. * + ? ( ) [ ] { } ^ $ | \ /
swiftgrasp.com # . 会匹配任意字符:
# 因此也会匹配 "swiftgraspXcom" ⚠
swiftgrasp\.com # ✓ 按字面匹配点号
$19.99 # $ 表示“字符串结尾”——永远匹配不到!
\$19\.99 # ✓ 按字面匹配美元符号和点号swiftgrasp.com 的确可以匹配 "swiftgrasp.com",所以测试会通过。问题是它还会匹配不该匹配的内容,往往要到生产环境遇到奇怪的边界情况才暴露。正则测试不能只测“应该匹配什么”,还必须断言“绝不能匹配什么”。下面是最常用的一组模式,都经过测试,也加了说明。先说清一个著名陷阱:不存在实用的“完美邮箱正则”。邮件规范允许许多怪异写法,生产系统通常只做简单格式检查,再发一封确认邮件。务实比死抠规范更可靠。
# 邮箱(务实版本——配合确认邮件使用)
^[\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真正熟练的人,知道什么时候应该拒绝正则。记住三条。固定文本不需要正则。嵌套结构,比如 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 # 每天都能用上的强大工具最后,把整页内容压缩成一张速查表。
# 字符类 # 量词
\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 → 真正的解析器到这里,初学开发者需要的技术栈就串起来了:Python → Git → 命令行 → SQL → HTTP → Docker → 正则表达式。七个页面,大约七十分钟音频,足够建立第一年动手做项目所需的基本词汇。现在去做一个东西吧。