首页 / Python3 入门教程 / 正则表达式

Python3 入门教程

正则表达式

本教程共 70 篇 · 第 51 篇 · 更新于 2026-07-22 · 约 5 分钟阅读

PythonPython3 入门教程正则表达式re模块re.sub分组提取

51. 正则表达式

本节目标:掌握 re 模块的基本用法,理解常用正则符号的含义,能写出匹配、搜索、替换的正则表达式。

正则表达式(Regular Expression,简称 regex)是一种描述文本模式的微型语言。它用一系列特殊符号定义「什么样的字符串符合条件」,在数据验证、文本提取、格式化等场景非常有用。

Python 通过 re 模块支持正则表达式。

基础匹配

import re

# 匹配字符串开头
result = re.match(r'hello', 'hello world')
print(result)       # <re.Match object; span=(0, 5), match='hello'>
print(result.group())  # hello

# 匹配失败返回 None
print(re.match(r'world', 'hello world'))  # None

re.match() 从字符串开头开始匹配。如果模式不在开头,返回 None

Tip

正则字符串前面加 r(raw string),让反斜杠不被 Python 转义。写正则时始终用 r'...',这是好习惯。

常用元字符

符号含义
.任意单个字符(除换行)
\d数字 [0-9]
\w单词字符 [a-zA-Z0-9_]
\s空白字符(空格、制表符、换行等)
\b单词边界
^字符串开头
$字符串结尾
*前一个字符出现 0 次或多次
+前一个字符出现 1 次或多次
?前一个字符出现 0 次或 1 次
{n}前一个字符恰好出现 n 次
{n,m}前一个字符出现 n 到 m 次
|
()分组
import re

print(re.match(r'\d+', '123abc').group())      # 123
print(re.match(r'\w+', 'hello_world').group()) # hello_world
print(re.match(r'a*b', 'aaab').group())        # aaab
print(re.match(r'colou?r', 'color').group())   # color

三种匹配方法的区别

函数行为
re.match()从字符串开头匹配
re.search()扫描整个字符串,返回第一个匹配
re.findall()返回所有匹配组成的列表
re.finditer()返回所有匹配的迭代器
text = 'The price is $25 and $30'

print(re.match(r'\$\d+', text))       # None($ 不在开头)
print(re.search(r'\$\d+', text).group())  # $25
print(re.findall(r'\$\d+', text))     # ['$25', '$30']
Note

日常用得最多的是 re.search()re.findall()match() 只在明确需要「从开头匹配」时使用,比如验证用户输入的格式。

分组提取

用括号 () 把模式分成组,可以单独提取:

import re

text = 'Name: Alice, Age: 25'
pattern = r'Name: (\w+), Age: (\d+)'

m = re.search(pattern, text)
print(m.group(0))   # 整个匹配:Name: Alice, Age: 25
print(m.group(1))   # 第一组:Alice
print(m.group(2))   # 第二组:25

给组起名字,代码更易读:

pattern = r'Name: (?P<name>\w+), Age: (?P<age>\d+)'
m = re.search(pattern, text)
print(m.group('name'))   # Alice
print(m.group('age'))    # 25

替换文本:re.sub()

import re

text = 'The color is red, I like red'
result = re.sub(r'red', 'blue', text)
print(result)  # The color is blue, I like blue

# 限制替换次数
result = re.sub(r'red', 'blue', text, count=1)
print(result)  # The color is blue, I like red

替换时可以用函数动态生成结果:

def double(m):
    num = int(m.group())
    return str(num * 2)

print(re.sub(r'\d+', double, '1 2 3'))  # 2 4 6

贪婪与非贪婪

正则默认是「贪婪」模式:尽可能匹配更多字符。

text = '<div>content</div>'
print(re.search(r'<.*>', text).group())   # <div>content</div>(贪婪)
print(re.search(r'<.*?>', text).group())  # <div>(非贪婪)

在量词后加 ? 变成非贪婪模式,匹配最少字符。

Warning

贪婪非贪婪选不对,是正则 bug 的高发区。写完后多测几个边界 case,尤其是标签、引号成对出现的情况。

编译正则:re.compile()

同一个正则表达式多次使用时,先编译能提升性能:

import re

email_pattern = re.compile(r'^[\w.-]+@[\w.-]+\.\w+$')

print(email_pattern.match('alice@example.com'))
print(email_pattern.match('bad-email'))

编译后的对象有 match()search()findall()sub() 等方法,和 re 模块的函数一一对应。

常见正则模式

import re

# 邮箱(简化版)
email = r'^[\w.-]+@[\w.-]+\.\w+$'

# 手机号(中国大陆)
phone = r'^1[3-9]\d{9}$'

# 身份证号(18 位)
idcard = r'^\d{17}[\dXx]$'

# IP 地址(简化版)
ip = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'

# 验证
def validate(pattern, text):
    return bool(re.match(pattern, text))

print(validate(phone, '13800138000'))  # True
print(validate(phone, '12345678901'))  # False
Note

正则表达式不是万能的。复杂的规则(比如邮箱的完整 RFC 规范)用正则表示会非常冗长。实际项目中,「够用即可」的简化版往往比 100% 准确的冗长版更实用。

小结

  • re.match() 从开头匹配,re.search() 全局找第一个,re.findall() 找全部。
  • () 分组提取,(?P<name>...) 命名分组。
  • re.sub() 替换文本,支持函数回调。
  • 量词默认贪婪,加 ? 变非贪婪。
  • 多次使用的正则先 compile(),性能更好。

正则表达式像一门浓缩的外语,符号密集,初学时看着头疼。但一旦掌握,处理字符串的效率会提升一个量级。不需要背下所有符号,记住最常用的十几个,遇到复杂模式再查文档。


来源:参考了 runoob「Python3 正则表达式」、liaoxuefeng「正则表达式」、pythondoc「re 模块」等,改写后所得。