Python 正则表达式(Regular Expressions)

更新于 2026-01-13

正则表达式是一种特殊的字符序列,用于匹配或查找其他字符串或字符串集合,它使用一种专门的语法来定义模式。正则表达式通常简称为 regexregexp

这类模式常被字符串搜索算法用于“查找”或“查找并替换”操作,或者用于输入验证。

在数据科学项目中进行大规模文本处理时,经常需要对文本数据进行操作。包括 Python 在内的许多编程语言都支持正则表达式处理。Python 标准库中的 re 模块提供了这一功能。

由于 re 模块中的大多数函数都使用原始字符串(raw strings),我们首先需要了解什么是原始字符串。


原始字符串(Raw Strings)

正则表达式使用反斜杠 \ 来表示特殊形式,或允许在不触发其特殊含义的情况下使用特殊字符。而 Python 本身也使用 \ 作为转义字符。因此,为了避免冲突,Python 推荐使用原始字符串表示法。

在字符串前加上 rR 前缀即可将其变为原始字符串:

>>> normal = "Hello"
>>> print(normal)
Hello
>>> raw = r"Hello"
>>> print(raw)
Hello

在一般情况下,两者没有区别。但当字符串中包含转义字符时,普通字符串会解释转义序列,而原始字符串则不会:

>>> normal = "Hello\nWorld"
>>> print(normal)
Hello
World
>>> raw = r"Hello\nWorld"
>>> print(raw)
Hello\nWorld

在上面的例子中,普通字符串打印时,\n 被解释为换行符;而原始字符串因前缀 r 的存在,\n 被原样输出。


元字符(Metacharacters)

大多数字母和字符都能直接匹配自身,但某些字符是元字符(metacharacters),具有特殊含义,不会匹配自身。常见的元字符包括:

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

方括号 [] 表示一个字符集合,可以列出单个字符,也可以用 - 表示范围。

序号 元字符 & 说明
1 [abc]:匹配 a、b 或 c 中任意一个字符
2 [a-c]:等价于 [abc]
3 [a-z]:仅匹配小写字母
4 [0-9]:仅匹配数字
5 [^5]:匹配除 5 以外的任意字符(^ 在方括号内表示取反)

反斜杠 \ 是转义元字符。若要匹配 [\ 本身,需在其前加反斜杠:$$\\

以下是以 \ 开头的预定义字符集(特殊序列):

序号 特殊序列 & 说明
1 \d:匹配任意十进制数字,等价于 [0-9]
2 \D:匹配任意非数字字符,等价于 [^0-9]
3 \s:匹配任意空白字符,等价于 [\t\n\r\f\v]
4 \S:匹配任意非空白字符
5 \w:匹配任意字母、数字或下划线,等价于 [a-zA-Z0-9_]
6 \W:匹配任意非字母数字字符
7 .:匹配除换行符 \n 外的任意单个字符
8 ?:匹配其左侧模式 0 次或 1 次
9 +:匹配其左侧模式 1 次或多次
10 *:匹配其左侧模式 0 次或多次
11 \b:单词边界;\B 为其反义
12 [..]:匹配方括号内的任意单个字符;[^..] 匹配不在其中的字符
13 \:用于转义特殊字符,如 \. 匹配句点,\+ 匹配加号
14 {n,m}:匹配前一个模式至少 n 次、至多 m 次
15 a|b:匹配 a 或 b

Python 的 re 模块常用函数

re.match() 函数

尝试从字符串开头匹配正则表达式模式。

语法:

re.match(pattern, string, flags=0)

参数说明:

参数 说明
pattern 要匹配的正则表达式
string 要搜索的字符串
flags 可选标志(如 re.I 表示忽略大小写)

返回值: 成功返回 Match 对象,失败返回 None

Match 对象方法:

  • .start():匹配起始位置
  • .end():匹配结束位置
  • .group(num=0):返回整个匹配内容(或指定子组)
  • .groups():返回所有子组组成的元组

示例:

import re
line = "Cats are smarter than dogs"
matchObj = re.match(r'Cats', line)
print(matchObj.start(), matchObj.end())        # 输出: 0 4
print("matchObj.group() :", matchObj.group())  # 输出: Cats

re.search() 函数

在整个字符串中搜索第一个匹配项(不限于开头)。

语法:

re.search(pattern, string, flags=0)

示例:

import re
line = "Cats are smarter than dogs"
matchObj = re.search(r'than', line)
print(matchObj.start(), matchObj.end())        # 输出: 17 21
print("matchObj.group() :", matchObj.group())  # 输出: than

匹配(match) vs 搜索(search)

  • match() 仅在字符串开头匹配。
  • search() 在字符串任意位置搜索第一个匹配。

示例:

import re
line = "Cats are smarter than dogs"
matchObj = re.match(r'dogs', line, re.M|re.I)
if matchObj:
    print("match -->", matchObj.group())
else:
    print("No match!!")  # 输出此行

searchObj = re.search(r'dogs', line, re.M|re.I)
if searchObj:
    print("search -->", searchObj.group())  # 输出: dogs
else:
    print("Nothing found!!")

输出:

No match!!
search --> dogs

re.findall() 函数

返回字符串中所有不重叠的匹配项,以列表形式返回。

语法:

re.findall(pattern, string, flags=0)

示例 1:

import re
string = "Simple is better than complex."
obj = re.findall(r"ple", string)
print(obj)  # ['ple', 'ple']

示例 2(提取单词):

obj = re.findall(r"\w*", string)
print(obj)  # ['Simple', '', 'is', '', 'better', '', 'than', '', 'complex', '', '']

注意:\w* 会匹配空字符串(因为 * 表示 0 次或多次),所以结果中有很多空字符串。


re.sub() 函数

用于替换匹配的字符串。

语法:

re.sub(pattern, repl, string, count=0)
  • count:最大替换次数(默认 0 表示全部替换)

示例 1(删除注释):

import re
phone = "2004-959-559 # This is Phone Number"
num = re.sub(r'#.*$', "", phone)
print("Phone Num :", num)  # 2004-959-559

示例 2(只保留数字):

num = re.sub(r'\D', "", phone)
print("Phone Num :", num)  # 2004959559

示例 3(单词替换):

string = "Simple is better than complex. Complex is better than complicated."
obj = re.sub(r'is', r'was', string)
print(obj)
# 输出: Simple was better than complex. Complex was better than complicated.

re.compile() 函数

将正则表达式编译为正则对象,便于重复使用,提高效率。

语法:

re.compile(pattern, flags=0)

常用标志(flags):

标志 说明
re.I 忽略大小写
re.L 使用当前区域设置(locale)
re.M 多行模式:^$ 匹配每行开头/结尾
re.S 单行模式:. 可匹配换行符
re.U 使用 Unicode 字符集(影响 \w, \b 等)
re.X 允许更清晰的正则写法(忽略空白和 # 注释)

示例:

import re
string = "Simple is better than complex. Complex is better than complicated."
pattern = re.compile(r'is')

# 使用编译后的对象
print(pattern.search(string).span())  # (7, 9)
print(pattern.findall(string))        # ['is', 'is']
print(pattern.sub('was', string))
# 输出: Simple was better than complex. Complex was better than complicated.

re.finditer() 函数

返回一个迭代器,逐个生成所有匹配的 Match 对象。

语法:

re.finditer(pattern, string, flags=0)

示例:

import re
string = "Simple is better than complex. Complex is better than complicated."
pattern = re.compile(r'is')
for match in pattern.finditer(string):
    print(match.span())
# 输出:
# (7, 9)
# (39, 41)

正则表达式的典型应用场景

查找所有副词(以 ly 结尾的单词)

import re
text = "He was carefully disguised but captured quickly by police."
obj = re.findall(r"\w+ly\b", text)
print(obj)  # ['carefully', 'quickly']

查找以元音字母开头的单词

import re
text = 'Errors should never pass silently. Unless explicitly silenced.'
obj = re.findall(r'\b[aeiouAEIOU]\w+', text)
print(obj)  # ['Errors', 'Unless', 'explicitly']

正则表达式修饰符(Flags)

修饰符 说明
re.I 忽略大小写
re.L 使用本地化设置
re.M 多行模式(^$ 匹配每行)
re.S 单行模式(. 匹配包括换行符在内的任意字符)
re.U Unicode 模式
re.X 扩展模式(忽略空格和 # 注释)

常用正则表达式模式汇总

序号 模式 说明
1 ^ 匹配行首
2 $ 匹配行尾
3 . 匹配除换行符外的任意字符
4 [...] 匹配括号内任意一个字符
5 [^...] 匹配不在括号内的任意字符
6 re* 匹配 0 次或多次
7 re+ 匹配 1 次或多次
8 re? 匹配 0 次或 1 次
9 re{n} 精确匹配 n 次
10 re{n,} 至少匹配 n 次
11 re{n,m} 匹配 n 到 m 次
12 a|b 匹配 a 或 b
13 (re) 分组并记住匹配内容
14–18 (?imx:...) 局部启用/禁用标志
19 (?#...) 注释
20 (?=re) 正向先行断言
21 (?!re) 负向先行断言
23–28 \w, \W, \s, \S, \d, \D 预定义字符类
29 \A 匹配字符串开头
30–31 \Z, \z 匹配字符串结尾
33–34 \b, \B 单词边界 / 非单词边界
36–37 \1...\9, \10 反向引用

示例分类

字面量字符

  • python → 匹配 "python"

字符类

  • [Pp]ython → 匹配 "Python" 或 "python"
  • [aeiou] → 匹配任意小写元音
  • [^0-9] → 匹配非数字

特殊字符类

  • \d → 数字
  • \w → 字母/数字/下划线
  • \s → 空白字符

重复

  • ruby? → "rub" 或 "ruby"
  • \d{3,5} → 3~5 位数字

非贪婪匹配

  • <.*?> → 匹配最短的 <...>(如 <python> 而非 <python>perl>

分组

  • ([Pp]ython(, )?)+ → 匹配 "Python", "Python, python" 等

反向引用

  • (['"])[^\1]*\1 → 匹配带引号的字符串(单引号或双引号)

锚点(位置匹配)

  • ^Python → 行首的 "Python"
  • \bPython\b → 完整单词 "Python"
  • Python(?=!) → 后面紧跟 ! 的 "Python"

特殊语法

  • R(?i:uby) → 在局部启用忽略大小写
  • rub(?:y|le) → 分组但不捕获(无反向引用)

正则表达式是文本处理的强大工具,掌握其核心语法和 re 模块的使用,能极大提升 Python 文本处理能力。