跳转至

re正则的应用

  1. 灵活,可处理任意文本和模式
  2. 不依赖结构,适合格式混乱的内容
  3. 语法简洁(简单场景)

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

功能:从字符串开头匹配模式,若匹配成功返回 Match 对象,否则返回 None。 示例:

1
2
import re
result = re.match(r'abc', 'abc123')  # 从开头匹配 'abc'

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

功能:在整个字符串中查找第一个匹配项,返回 Match 对象或 None(与 match 区别:不限制开头)。 示例:

1
2
result = re.search(r'\d+', 'abc123def456')  # 查找第一个数字串
print(result.group())  # 输出:123

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

功能:查找所有匹配项,返回列表(包含所有匹配的字符串)。 示例:

1
2
result = re.findall(r'\d+', 'abc123def456')  # 查找所有数字串
print(result)  # 输出:['123', '456']

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

功能:查找所有匹配项,返回迭代器(每个元素是 Match 对象,适合大量结果时节省内存)。 示例:

1
2
for match in re.finditer(r'\d+', 'abc123def456'):
    print(match.group())  # 依次输出:123、456

5. re.sub(pattern, repl, string, count=0, flags=0)

功能:替换字符串中所有匹配项,repl 为替换后的内容(可是字符串或函数)。 示例:

1
2
3
4
5
6
7
8
9
# 替换数字为 'X'
result = re.sub(r'\d+', 'X', 'abc123def456')
print(result)  # 输出:abcXdefX

# 用函数处理替换(将数字加 1)
def add_one(match):
    return str(int(match.group()) + 1)
result = re.sub(r'\d+', add_one, '123, 456')
print(result)  # 输出:124, 457

6. re.split(pattern, string, maxsplit=0, flags=0)

功能:根据匹配的模式分割字符串,返回列表。 示例:

1
2
3
# 用逗号或空格分割
result = re.split(r'[, ]', 'a,b c,d')
print(result)  # 输出:['a', 'b', 'c', 'd']

7. re.compile(pattern, flags=0)

功能:编译正则表达式为 Pattern 对象,可重复使用(提升多次匹配效率)。 示例:

1
2
3
pattern = re.compile(r'\d+')  # 预编译
print(pattern.findall('abc123def456'))  # 输出:['123', '456']
print(pattern.sub('X', 'test789'))      # 输出:testX

Match 对象常用方法

当 match 或 search 匹配成功时,返回 Match 对象,常用方法: group(num=0):返回第 num 个分组的匹配内容(num=0 表示整个匹配)。

.*? 的典型应用场景

1. 提取两个固定字符之间的内容

当需要提取 “以 A 开头、以 B 结尾” 的中间部分,且 A 和 B 可能多次出现时,.*? 能精准定位到第一对 A 和 B 之间的内容。 示例:提取 start 和 end 之间的内容

1
2
3
text = 'xxx start:提取这段内容 end yyy start:不要提取这段 end zzz'
pattern = r'start:(.*?)end'  # 匹配 start: 到第一个 end 之间的内容
print(re.findall(pattern, text)[0])  # 输出:['提取这段内容 ']

2. 忽略 HTML/XML 标签中的无关内容

在解析标签时,.*? 可避免匹配到多余的标签对,精准提取目标标签内的信息。 示例:提取所有 标签的 href 属性值

1
2
3
html = '<a href="link1">链接1</a><a href="link2">链接2</a>'
pattern = r'href="(.*?)"'  # 匹配 href=" 和 " 之间的内容
print(re.findall(pattern, html))  # 输出:['link1', 'link2']

3. 处理换行符(配合 re.DOTALL 标志)

默认情况下,. 不匹配换行符 \n,若需匹配包含换行的内容,可结合 re.DOTALL(让 . 匹配换行)和 .*?。 示例:提取跨多行的注释内容

1
2
3
4
5
6
7
text = '''/* 这是
一段跨多行的
注释 */ 其他内容 /* 另一段注释 */'''
pattern = r'/\*(.*?)\*/'  # 匹配 /* 和 */ 之间的内容(包括换行)
# 注意:需设置 re.DOTALL 让 . 匹配换行
print(re.findall(pattern, text, re.DOTALL))
# 输出:[' 这是\n一段跨多行的\n注释 ', ' 另一段注释 ']

4. 清洗不规则字符串中的冗余内容

当字符串格式不固定,但存在明确的 “起始标记” 和 “结束标记” 时,.*? 可高效提取核心信息。 示例:从日志中提取用户 ID

1
2
3
log = '2023-10-01 12:00 [INFO] user_id=123; action=login | 2023-10-01 12:01 [INFO] user_id=456; action=logout'
pattern = r'user_id=(.*?);'  # 匹配 user_id= 到第一个 ; 之间的内容
print(re.findall(pattern, log))  # 输出:['123', '456']

?P

?P:这是 Python re 模块中用于命名分组的语法(P 是大写)。 作用:将括号内的匹配内容标记为一个 “命名分组”,分组名称为 <> 中的 name。 后续可通过 Match对象.group('name') 直接获取该分组的内容,比通过索引(如 group(1))更直观。 .?:如前所述,是非贪婪匹配模式,匹配任意字符(尽可能少的字符),直到遇到后续条件为止。 完整模式 (?P.?) 的作用: 创建一个名为 name 的分组,该分组匹配 “任意字符(非贪婪模式)”,常用于精准提取两个标记之间的内容,并给这段内容命名以便引用。

1
2
3
4
5
6
7
text = "姓名:张三,年龄:25,性别:男"
# 提取姓名、年龄、性别,分别命名分组
pattern = r'姓名:(?P<name>.*?),年龄:(?P<age>.*?),性别:(?P<gender>.*?)'

match = re.match(pattern, text)
print(match.group('name'))    # 输出:张三
print(match.group('age'))     # 输出:25