Python re模块的常用函数和正则表达式核心语法

 更新时间:2026年05月07日 09:21:51   作者:曾阿伦  
文章总结了re模块的常用函数、正则语法、场景应用、高级技巧及常见问题,介绍了匹配、提取、编译等函数及正则表达式语法,提供了手机号、邮箱等场景示例,并讲解了分组提取、非贪婪匹配等高级用法,需要的朋友可以参考下

一、核心前提:re 模块常用函数速查

函数作用核心参数返回值场景
re.match(pattern, string)从字符串开头匹配pattern(正则表达式)、string(目标字符串)匹配对象 / None前缀验证(如手机号、邮箱前缀)
re.search(pattern, string)字符串任意位置匹配(首次)同上匹配对象 / None提取任意位置的目标内容
re.findall(pattern, string)匹配所有符合规则的内容同上列表(含所有匹配结果)批量提取(如所有链接、手机号)
re.finditer(pattern, string)迭代器形式返回所有匹配同上迭代器(含匹配对象)大量数据提取(省内存)
re.sub(pattern, repl, string)替换匹配内容新增 repl(替换字符串 / 函数)替换后的字符串清洗数据(如去除特殊字符)
re.compile(pattern)编译正则表达式pattern编译后的正则对象重复使用同一正则(提效)

关键说明:

  1. 匹配对象常用方法:group()(获取匹配结果)、groups()(获取分组结果)、span()(获取匹配位置);
  2. 修饰符:re.I(忽略大小写)、re.S(. 匹配换行)、re.M(多行匹配),可组合使用(如 re.I | re.S)。

二、正则语法核心片段

语法说明示例匹配结果
^字符串开头^1[3-9]匹配以 13-19 开头的字符串
$字符串结尾[0-9]$匹配以数字结尾的字符串
.匹配任意字符(除换行)a.b匹配 a + 任意字符 + b(如 acb、aab)
*前面字符出现 0-∞ 次ab*匹配 a、ab、abb…
+前面字符出现 1-∞ 次ab+匹配 ab、abb、abbb…
?前面字符出现 0-1 次(非贪婪)ab?匹配 a、ab
{n}前面字符出现 n 次a{3}匹配 aaa
{n,m}前面字符出现 n-m 次a{2,4}匹配 aa、aaa、aaaa
[]字符集(匹配其中一个)[a-zA-Z0-9]匹配字母 / 数字
[^]反向字符集[^0-9]匹配非数字字符
\d匹配数字(等价 [0-9])\d{3}匹配 123、456…
\D匹配非数字\D+匹配 abc、中文…
\w匹配字母 / 数字 / 下划线\w+匹配 username123、test_abc
\W匹配非字母 / 数字 / 下划线\W匹配 @、#、空格…
\s匹配空白字符(空格 / 制表符 / 换行)\s+匹配多个空白
\S匹配非空白字符\S+匹配非空白内容
()分组(提取目标内容)(\d{3})-(\d{4})分组 1 匹配前 3 位,分组 2 匹配后 4 位
``或逻辑`abc

三、场景:判断与提取

所有场景均基于 re 模块,直接复制可用,标注「判断」「提取」明确用途。

场景 1:手机号判断与提取

  • 规则:11 位数字,以 13/14/15/17/18/19 开头
import re

def check_phone(phone):

   """判断是否为有效手机号(返回布尔值)"""

   pattern = r'^1[3-9]\d{9}$'  # ^$ 严格匹配整个字符串

   return bool(re.match(pattern, phone))

def extract_phones(text):

   """从文本中提取所有手机号(返回列表)"""

   pattern = r'1[3-9]\d{9}'  # 无需^$,匹配任意位置

   return re.findall(pattern, text)

# 测试

print(check_phone("13812345678"))  # True

print(extract_phones("联系电话:13987654321,备用15600001111"))  # ['13987654321', '15600001111']

场景 2:邮箱判断与提取

  • 规则:用户名 @域名(支持字母、数字、下划线、点号)
def check_email(email):

   """判断是否为有效邮箱"""

   pattern = r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+.[a-zA-Z]{2,6}$'

   return bool(re.match(pattern, email))

def extract_emails(text):

   """提取文本中所有邮箱"""

   pattern = r'[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+.[a-zA-Z]{2,6}'

   return re.findall(pattern, text)

# 测试

print(check_email("test123@example.com"))  # True

print(extract_emails("邮箱:user_name@qq.com,工作邮箱work.123@gmail.com"))  # ['user_name@qq.com', 'work.123@gmail.com']

场景 3:提取 URL 链接

  • 规则:匹配 http/https 开头的链接
def extract_urls(text):

   pattern = r'https?://[^\s]+'  # http或https开头,直到空白字符结束

   return re.findall(pattern, text)

# 测试

text = "推荐网站:https://www.csdn.net,文档https://docs.python.org"

print(extract_urls(text))  # ['https://www.csdn.net', 'https://docs.python.org']

场景 4:提取身份证号(18 位)

  • 规则:17 位数字 + 最后 1 位(数字 / X/x)
def extract_id_cards(text):

   pattern = r'\d{17}[\dXx]'

   return re.findall(pattern, text)

# 测试

text = "身份证:110101199001011234,备用22020219800202567X"

print(extract_id_cards(text))  # ['110101199001011234', '22020219800202567X']

场景 5:提取中文(含短语)

def extract_chinese(text):

   pattern = r'[\u4e00-\u9fa5]+'  # 中文Unicode范围

   return re.findall(pattern, text)

# 测试

text = "Python正则表达式提取中文:你好,世界!123abc"

print(extract_chinese(text))  # ['正则表达式提取中文', '你好', '世界']

场景 6:提取数字(整数 + 小数)

def extract_numbers(text):

   pattern = r'-?\d+.?\d*'  # 支持负数、整数、小数

   return re.findall(pattern, text)

# 测试

text = "价格:99元,折扣价89.9元,亏损-10.5元"

print(extract_numbers(text))  # ['99', '89.9', '-10.5']

场景 7:验证密码强度(判断)

  • 规则:8-16 位,含字母 + 数字 + 特殊字符(@#$%^&*)
def check_password_strength(password):

   """判断密码是否符合强密码规则"""

   # 三个条件同时满足:长度8-16、含字母、含数字、含特殊字符

   pattern = r'^(?=.*[a-zA-Z])(?=.*\d)(?=.*[@#$%^&*])[a-zA-Z0-9@#$%^&*]{8,16}$'

   return bool(re.match(pattern, password))

# 测试

print(check_password_strength("Test123@"))  # True

print(check_password_strength("weakpassword"))  # False(无数字和特殊字符)

四、高级技巧:分组提取与非贪婪匹配

1. 分组提取

例如:提取「姓名:张三,年龄:25」中的姓名和年龄

text = "用户信息:姓名:张三,年龄:25,性别:男"

pattern = r'姓名:([^\u4e00-\u9fa5]+),年龄:(\d+)'  # 分组1匹配姓名,分组2匹配年龄

result = re.search(pattern, text)

if result:

   name = result.group(1)

   age = result.group(2)

   print(f"姓名:{name},年龄:{age}")  # 姓名:张三,年龄:25

2. 非贪婪匹配

问题:.* 默认贪婪(匹配尽可能多的内容),需用 .*? 非贪婪

例如,正则表达式 a.*b 在字符串 ‘a123b456b’ 中,.* 会一口气吃掉从第一个 a 之后到最后一个 b 之前的所有字符,最终匹配的是 ‘a123b456b’ 整个子串,而不是我们可能期望的 ‘a123b’。

非贪婪匹配:在量词后面加上 ?,量词会尽可能少地重复匹配,只要能让整个表达式匹配成功。正则表达式改为 a.*?b ,得到 ‘a123b’。

贪婪写法非贪婪写法说明
**?零次或多次,尽可能少
++?一次或多次,尽可能少
???零次或一次,倾向于零次
{m,n}{m,n}?至少 m 次,至多 n 次,尽可能少
# 提取 HTML 标签内容
html = '<div>第一段</div><div>第二段</div>'

# 贪婪匹配:.* 会匹配到最后一个 </div>
greedy_tags = re.findall(r'<div>(.*)</div>', html)
print("贪婪匹配提取内容:", greedy_tags)   # 输出: ['第一段</div><div>第二段']

# 非贪婪匹配:.*? 只匹配到最近的 </div>
non_greedy_tags = re.findall(r'<div>(.*?)</div>', html)
print("非贪婪匹配提取内容:", non_greedy_tags)  # 输出: ['第一段', '第二段']

在正则表达式中,? 有两种用法:

  • 作为普通量词,表示“零次或一次”(贪婪)。
  • 跟在其他量词后面,表示将贪婪变为非贪婪(懒惰)。

例如:

  • .*? 表示“任意字符重复零次或多次,但尽可能少”。
  • .+? 表示“任意字符重复一次或多次,但尽可能少”。
  • a?? 表示“匹配一个 a 或零个 a,但优先零个”。
# ?? 示例:匹配两个字符,但尽可能少
print(re.findall(r'a??', 'aa'))   # 输出: ['', 'a', '']  因为第一个位置优先匹配0个a

五、常见问题与避坑指南

  1. 匹配不到换行符

问题:. 默认不匹配换行,需加修饰符 re.S

示例:re.search(r'a.b', 'a\nb', re.S) → 匹配成功

  1. 忽略大小写匹配

加修饰符 re.I,示例:re.match(r'abc', 'ABC', re.I) → 匹配成功

  1. 正则中有特殊字符(如 . * ?)

需转义(加 \)或用 re.escape() 自动转义

示例:匹配 www.baidu.compattern = r'www\.baidu\.com'pattern = re.escape('www.baidu.com')

  1. 重复使用同一正则

re.compile() 编译,提升效率

示例:

pattern = re.compile(r'1[3-9]\d{9}')

print(pattern.match("13812345678"))  # 直接使用编译后的对象

print(pattern.findall("联系电话13987654321"))

六、常用

需求正则表达式Python 代码片段
判断手机号^1[3-9]\d{9}$re.match(r'^1[3-9]\d{9}$', phone)
判断邮箱^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+.[a-zA-Z]{2,6}$re.match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+.[a-zA-Z]{2,6}$', email)
提取手机号1[3-9]\d{9}re.findall(r'1[3-9]\d{9}', text)
提取邮箱[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+.[a-zA-Z]{2,6}re.findall(r'[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+.[a-zA-Z]{2,6}', text)
提取中文[\u4e00-\u9fa5]+re.findall(r'[\u4e00-\u9fa5]+', text)
提取数字(含小数)-?\d+.?\d*re.findall(r'-?\d+.?\d*', text)
提取 URLhttps?://[^\s]+re.findall(r'https?://[^\s]+', text)

以上就是Python正则表达式备忘录判断与提取核心用法的详细内容,更多关于Python正则表达式备忘录的资料请关注脚本之家其它相关文章!

相关文章

最新评论