小白学 Python
课程GitHub
© 2026 小白学 Python · 基于 walter201230/Python 教程
课程目录GitHub
Python 环境加载中…
正则表达式0 / 4
1234

正则表达式

4 道练习题·预计 35 分钟·做对一题解锁下一段

教学 01 / 05· 已读

第一节:正则表达式

正则表达式(Regular Expression,简称 regex) 是一种用「特殊字符序列」描述字符串模式的语言。

它能回答这一类问题:

  • 这个字符串里有没有手机号?
  • 这段文字里所有的邮箱抓出来
  • 把多余的空白替换成一个空格
  • 这段输入是不是合法的身份证号?

Python 自 1.5 版本起就内置了 re 模块,提供 Perl 风格的正则功能。

用 Python 字符串能解决的,就别用正则

先看一个反面例子。要判断字符串里是否包含某段固定文字,根本不需要正则:

python
a = '两点水|twowater|liangdianshui|草根程序员'

print('两点水' in a)   # True
print(a.index('两点水') > -1)  # True

这种纯「子串查找」用 in 就够了。

正则的强项:「带规则」的查找

正则真正发力的地方是——你不知道具体的字符是什么,但知道它们的形状。比如:

「找出字符串里所有的连续小写字母」

python
import re

a = '两点水|twowater|liangdianshui|草根程序员'
print(re.findall('[a-z]+', a))
# ['twowater', 'liangdianshui']

[a-z]+ 就是一条「规则」:

  • [a-z] 代表「任何一个小写字母」
  • + 代表「连续出现一次以上」

合起来就是「一段小写字母」。re.findall 把字符串里所有匹配的片段都列出来。

本节学习路线

  1. 元字符 + 量词:写出第一条正则规则
  2. re.match / re.search / re.findall:三个最常用的函数
  3. 分组 (...):从匹配里提取片段
  4. re.sub:基于规则做替换

学完你就有能力写出「找手机号」「抓邮箱」「清洗多余空格」这类常用工具了。

教学 02 / 05

二、元字符与量词

正则之所以「叫正则」,是因为它有一套自己的小语法。这里只学最常用的两类:字符集 / 元字符 和 量词。

1、字符集 [...]:「或」的关系

方括号 [...] 里写一组字符,表示匹配其中任意一个。

python
import re

a = 'uav,ubv,ucv,uwv,uzv,uov'

# 取 u 和 v 中间是 a / b / c 的
print(re.findall('u[abc]v', a))
# ['uav', 'ubv', 'ucv']

# 连续字母可以用 - 缩写
print(re.findall('u[a-c]v', a))
# ['uav', 'ubv', 'ucv']

# 取反:u 和 v 中间不是 a / b / c 的
print(re.findall('u[^abc]v', a))
# ['uwv', 'uzv', 'uov']

要点:

  • [abc] 是 a 或 b 或 c
  • [a-z] 是连续范围:所有小写字母
  • [^abc] 在开头加 ^ 表示取反

2、概括字符集(最常用)

下面这几个是最常用的预定义字符集,建议记下来:

写法等价含义
\d[0-9]任何数字
\D[^0-9]非数字
\w[A-Za-z0-9_]单词字符(字母 / 数字 / 下划线)
\W[^A-Za-z0-9_]非单词字符
\s[ \t\n\r\f\v]空白字符
\S非空白字符
.任意一个字符(除换行外)
python
import re

a = 'hi 123-abc'
print(re.findall(r'\d', a))   # ['1', '2', '3']
print(re.findall(r'\w', a))   # ['h', 'i', '1', '2', '3', 'a', 'b', 'c']

注意:正则字符串里反斜杠 \ 容易和 Python 自身的转义冲突——养成习惯,正则全部用 r'...' 原始字符串。

3、量词

光匹配「一个」字符不够用。我们要表达重复几次,就要用量词:

写法含义
?0 次或 1 次
+1 次或多次
*0 次或多次
{n}恰好 n 次
{n,m}n 到 m 次
{n,}至少 n 次

例子——找出 4 到 7 个字母组成的英文单词:

python
import re

a = 'java*&39android##@@python'
print(re.findall('[a-z]{4,7}', a))
# ['java', 'android', 'python']

4、贪婪 vs 非贪婪

默认量词是贪婪的——能多吃就多吃:

python
print(re.findall('[a-z]{4,7}', 'android'))
# ['android']  ← 一次吃满 7 个

在量词后面加 ? 变成非贪婪——能少吃就少吃:

python
print(re.findall('[a-z]{4,7}?', 'android'))
# ['andr']     ← 只吃 4 个就回头
贪婪非贪婪描述
???0 次或 1 次
++?1 次或多次
**?0 次或多次
{n,m}{n,m}?n 到 m 次

经验:写正则时默认是贪婪——这往往不是你想要的。要小心,必要时加 ?。

练习 2 / 4·用 re.findall 抓出全部数字🔒 完成上一题后解锁题目有问题?

字符串 'abc123def456ghi789' 里夹杂着一些连续的数字段。

请用 re.findall 把所有连续数字段抓出来,赋给变量 nums,然后 print(nums)。

输出应该是:

['123', '456', '789']

提示:连续数字可以用 \d+。

main.py
🔒 未解锁
🔒做对当前题解锁下一段 ·0/4
本章目录

正则表达式

  1. 教学 01第一节:正则表达式
  2. 教学 02二、元字符与量词
  3. 练习 2 🔒用 re.findall 抓出全部数字
  4. 教学 05三、`re.match` / `re.search` / `re.findall`
  5. 练习 1用 re.match 校验手机号
  6. 教学 03四、分组 `(...)`:从匹配里提取片段
  7. 练习 3 🔒用分组提取邮箱的用户名和域名
  8. 教学 04五、`re.sub`:基于规则替换
  9. 练习 4 🔒用 re.sub 把多空格压成单空格
← 上一章13 · 线程与进程
正则表达式
下一章 →15 · 闭包