Python 正则表达式模块 re
flyfish
一、正则表达式基础
1. 什么是正则表达式?
正则表达式(Regular Expression, RE)是一种用于匹配、查找和替换文本模式的工具,由普通字符(如字母、数字)和特殊字符(元字符)组成。
2. 常用元字符
| 元字符 | 说明 | 示例 | 
|---|---|---|
| . | 匹配任意单个字符(除换行符) | a.c→abc,adc | 
| \w | 匹配字母、数字或下划线 | \w+→hello123 | 
| \d | 匹配数字 | \d{3}→123 | 
| \s | 匹配空白字符(空格、制表符等) | \s+→ 多个空格 | 
| * | 匹配前一个字符零次或多次 | ab*→a,ab,abb | 
| + | 匹配前一个字符一次或多次 | ab+→ab,abb | 
| ? | 匹配前一个字符零次或一次 | ab?→a或ab | 
| ^ | 匹配字符串开头 | ^abc→ 以abc开头 | 
| $ | 匹配字符串结尾 | abc$→ 以abc结尾 | 
二、Python 正则表达式模块 re
1. 模块导入
import re
2. 常用函数
| 函数名 | 作用描述 | 
|---|---|
| re.compile() | 编译正则表达式,提高重复使用效率 | 
| re.match() | 从字符串开头匹配模式 | 
| re.search() | 在字符串任意位置搜索模式 | 
| re.findall() | 查找所有匹配项,返回列表 | 
| re.finditer() | 查找所有匹配项,返回迭代器 | 
| re.sub() | 替换匹配项 | 
| re.subn() | 替换匹配项并返回替换次数 | 
| re.split() | 按模式分割字符串 | 
| re.fullmatch() | 要求整个字符串完全匹配模式 | 
三、核心功能详解
1. 匹配操作
- re.match()(从开头匹配)- match = re.match(r'hello', 'hello world') print(match.group()) # 输出: hello
match = re.search(r'```json(.*?)```', content, re.DOTALL)
re.search() 函数
re.search(pattern, string, flags=0) 是 re 模块中的一个函数,用于在字符串 string 中搜索第一个与模式 pattern 匹配的子字符串。如果找到匹配项,则返回一个匹配对象;如果没有找到,则返回 None。
- pattern:要搜索的正则表达式模式。
- string:要在其中进行搜索的字符串,这里是- content。
- flags:可选参数,用于指定正则表达式的匹配模式。这里使用了- re.DOTALL。
正则表达式模式 r'```json(.*?)```'
- r:在字符串前面加上- r表示这是一个原始字符串。在原始字符串中,反斜杠- \不会被当作转义字符处理,这样可以避免在编写正则表达式时出现过多的转义字符,提高代码的可读性。
- json ````:这是一个普通的字符串,表示匹配以json ````开头的文本。
- (.*?):这是一个捕获组,用于匹配任意字符(除换行符外,除非使用了- re.DOTALL标志)。- .:匹配除换行符外的任意单个字符。
- *:表示前面的字符(即- .)可以出现零次或多次。
- ?:在- *后面加上- ?表示非贪婪匹配。贪婪匹配会尽可能多地匹配字符,而非贪婪匹配会尽可能少地匹配字符。例如,如果字符串中有多个- json...代码块,非贪婪匹配会只匹配到第一个 ```````````就停止。
 
- :表示匹配以结尾的文本。
re.DOTALL 标志
re.DOTALL 是 re 模块中的一个标志,它会改变 . 的匹配行为。默认情况下,. 不匹配换行符,但使用 re.DOTALL 后,. 可以匹配包括换行符在内的任意字符。这意味着代码块中可以包含换行符,能够正确匹配多行的 JSON 代码块。
- re.search()(全局搜索)- search = re.search(r'world', 'hello world') print(search.group()) # 输出: world
2. 查找所有匹配项
- re.findall()- numbers = re.findall(r'\d+', 'a123b456c') print(numbers) # 输出: ['123', '456']
3. 替换操作
- re.sub()- text = re.sub(r'\d+', 'X', 'a123b456c') print(text) # 输出: aXbXc
4. 分割字符串
- re.split()- parts = re.split(r'\s+', 'hello world') print(parts) # 输出: ['hello', 'world']
四、捕获组与 group() 方法
1. 基本用法
pattern = r'(\d{4})-(\d{2})-(\d{2})'
date_str = '2025-03-11'
match = re.search(pattern, date_str)
print(match.group(0))  # 完整匹配结果 → '2025-03-11'
print(match.group(1))  # 第一个捕获组 → '2025'
print(match.group(2))  # 第二个捕获组 → '03'
print(match.group(3))  # 第三个捕获组 → '11'
2. 查看捕获组数量
- 使用 groups()groups = match.groups() print(len(groups)) # 输出: 3
- 命名捕获组(使用 groupdict())pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})' match = re.search(pattern, date_str) print(match.groupdict()) # 输出: {'year': '2025', 'month': '03', 'day': '11'}
五、re.match vs re.search
基本概念对比
- re.match:该函数会从字符串的起始位置开始尝试匹配正则表达式模式。如果字符串的起始位置不符合模式,即使字符串的其他部分存在匹配内容,- re.match也会返回- None。也就是说,它要求模式必须从字符串的第一个字符开始匹配成功。
- re.search:此函数会在整个字符串中进行搜索,查找与正则表达式模式匹配的第一个位置。只要字符串中存在一处符合模式的内容,- re.search就会返回一个匹配对象。
详细示例对比
示例 1:模式在字符串起始位置匹配
import re
# 定义字符串和模式
pattern = r'hello'
string = 'hello world'
# 使用 re.match
match_result = re.match(pattern, string)
if match_result:
    print("re.match 匹配成功,匹配内容为:", match_result.group())
else:
    print("re.match 匹配失败")
# 使用 re.search
search_result = re.search(pattern, string)
if search_result:
    print("re.search 匹配成功,匹配内容为:", search_result.group())
else:
    print("re.search 匹配失败")
结果分析:在这个例子中,模式 'hello' 位于字符串 'hello world' 的起始位置。因此,re.match 和 re.search 都能成功匹配,并且都能返回匹配到的 'hello'。
示例 2:模式不在字符串起始位置
import re
# 定义字符串和模式
pattern = r'world'
string = 'hello world'
# 使用 re.match
match_result = re.match(pattern, string)
if match_result:
    print("re.match 匹配成功,匹配内容为:", match_result.group())
else:
    print("re.match 匹配失败")
# 使用 re.search
search_result = re.search(pattern, string)
if search_result:
    print("re.search 匹配成功,匹配内容为:", search_result.group())
else:
    print("re.search 匹配失败")
结果分析:模式 'world' 不在字符串 'hello world' 的起始位置,所以 re.match 会匹配失败,返回 None。而 re.search 会在整个字符串中搜索,能够找到 'world' 并返回匹配对象,输出匹配内容 'world'。
示例 3:模式部分在起始位置但不完全匹配
import re
# 定义字符串和模式
pattern = r'hello world!'
string = 'hello world'
# 使用 re.match
match_result = re.match(pattern, string)
if match_result:
    print("re.match 匹配成功,匹配内容为:", match_result.group())
else:
    print("re.match 匹配失败")
# 使用 re.search
search_result = re.search(pattern, string)
if search_result:
    print("re.search 匹配成功,匹配内容为:", search_result.group())
else:
    print("re.search 匹配失败")
结果分析:模式 'hello world!' 虽然前部分 'hello world' 与字符串起始部分相同,但整体模式不完全匹配,所以 re.match 会失败。re.search 同样在整个字符串中找不到完全匹配的内容,也会匹配失败。
性能考虑
- re.match:由于它只从字符串起始位置开始匹配,不需要对整个字符串进行遍历,在某些情况下性能可能会更好,特别是当你明确知道要匹配的内容应该在字符串开头时。
- re.search:需要遍历整个字符串来查找匹配位置,所以在处理较长字符串时,性能可能会相对较低。但它的灵活性更高,适用于不确定匹配内容位置的情况。
六、正则表达式 re 模块的常用例子
1. 匹配以特定字符开头的字符串
import re
text = "apple banana cherry"
pattern = r'^apple'
result = re.search(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
2. 匹配以特定字符结尾的字符串
import re
text = "apple banana cherry"
pattern = r'cherry$'
result = re.search(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
3. 匹配包含特定单词的字符串
import re
text = "The quick brown fox jumps over the lazy dog"
pattern = r'fox'
result = re.search(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
4. 匹配连续数字
import re
text = "abc123def"
pattern = r'\d+'
result = re.findall(pattern, text)
print("匹配结果:", result)
5. 匹配字母和数字的组合
import re
text = "abc123def"
pattern = r'[a-zA-Z0-9]+'
result = re.findall(pattern, text)
print("匹配结果:", result)
6. 匹配邮箱地址
import re
text = "example@example.com"
pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
result = re.fullmatch(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
7. 匹配手机号码
import re
text = "13800138000"
pattern = r'^1[3-9]\d{9}$'
result = re.fullmatch(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
8. 匹配日期格式(YYYY-MM-DD)
import re
text = "2025-03-11"
pattern = r'^\d{4}-\d{2}-\d{2}$'
result = re.fullmatch(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
9. 替换所有数字为指定字符
import re
text = "abc123def456"
pattern = r'\d+'
replacement = 'X'
result = re.sub(pattern, replacement, text)
print("替换结果:", result)
10. 分割字符串
import re
text = "apple,banana,cherry"
pattern = r','
result = re.split(pattern, text)
print("分割结果:", result)
11. 提取 HTML 标签中的内容
import re
html = '<p>Hello, World!</p>'
pattern = r'<p>(.*?)</p>'
result = re.findall(pattern, html)
print("提取结果:", result)
12. 匹配中文
import re
text = "你好,世界!"
pattern = r'[\u4e00-\u9fa5]+'
result = re.findall(pattern, text)
print("匹配结果:", result)
13. 匹配多个单词中的任意一个
import re
text = "cat dog elephant"
pattern = r'cat|dog'
result = re.findall(pattern, text)
print("匹配结果:", result)
14. 匹配重复的字符
import re
text = "aaaaabbbccc"
pattern = r'(.)\1+'
result = re.findall(pattern, text)
print("匹配结果:", result)
15. 匹配不包含特定字符的字符串
import re
text = "abcde"
pattern = r'[^abc]+'
result = re.findall(pattern, text)
print("匹配结果:", result)
16. 匹配单词边界
import re
text = "The quick brown fox jumps"
pattern = r'\bfox\b'
result = re.search(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
17. 匹配 IP 地址
import re
text = "192.168.1.1"
pattern = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
result = re.fullmatch(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
18. 匹配 URL
import re
text = "https://www.example.com"
pattern = r'^https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+'
result = re.fullmatch(pattern, text)
if result:
    print("匹配成功:", result.group())
else:
    print("匹配失败")
19. 统计匹配次数
import re
text = "apple apple banana cherry apple"
pattern = r'apple'
matches = re.findall(pattern, text)
count = len(matches)
print("匹配次数:", count)
20. 使用编译后的正则表达式进行匹配
import re
text = "abc123def"
pattern = re.compile(r'\d+')
result = pattern.findall(text)
print("匹配结果:", result)