注意:在常见符号前加个 \ 代表转义符
在日常编程中,文本处理 是绕不开的场景:验证邮箱、手机号,提取网页中的链接,替换敏感词,分割日志内容...... 如果用原生字符串方法逐字判断,代码会又长又难维护。而正则表达式 就是解决这类问题的「神器」,它用一套简洁的规则,就能实现复杂的文本匹配、提取、替换。
今天这篇博客,带你从零到一掌握 Python 正则表达式,覆盖核心语法、内置模块、实战案例,看完就能直接用在项目里!
一、什么是正则表达式?
正则表达式(Regular Expression,简称正则 / Regex ,在 Python 中称为 Reg ),是用于匹配字符串的规则公式 。
简单说:你写一段「规则」,正则引擎会拿着这段规则,去目标文本中找符合规则的内容 。
举个最简单的例子:
规则 \\d 代表「匹配一个数字」,用它去匹配字符串 python123,就能找到 1、2、3 三个数字。
二、Python 正则核心模块:re 模块
Python 自带正则处理工具 ------re**** 模块,无需额外安装,直接导入即可使用:
python
import re
01_re 模块 match 匹配方式
re\.match\(\) 是从字符串开头进行匹配的方法:
-
必须从第一个字符开始匹配规则
-
匹配成功返回匹配对象,失败返回
None -
常用
\.group\(\)获取匹配结果
代码示例
python
import re
def get_data(result):
if result:
return result.group()
return "匹配失败"
# 正确匹配:开头符合规则
res1 = re.match('python', 'python正则')
print(get_data(res1)) # python
# 错误匹配:开头不符合
res2 = re.match('python', '学习python正则')
print(get_data(res2)) # 匹配失败
02_re 模块 search 匹配方式
re\.search\(\) 会扫描整个字符串 ,找到第一个符合规则的内容就停止:
-
不限制必须从开头匹配
-
只返回第一个匹配结果
代码示例
python
import re
def get_data(result):
if result:
return result.group()
return "匹配失败"
# 在任意位置查找数字
res = re.search('\d+', 'python123java456')
print(get_data(res)) # 123
03_re 模块 findall 匹配方式
re\.findall\(\) 是最常用方法:
-
查找字符串中所有符合规则的内容
-
直接返回列表 ,无需
\.group\(\)
代码示例
python
import re
# 提取所有数字
res = re.findall('\d+', '价格99元,折扣8折,库存100件')
print(res) # ['99', '8', '100']
三、正则表达式基础语法
04_正则表达式匹配单个字符
匹配一个字符的核心规则:
| 符号 | 含义 |
|---|---|
\. |
匹配除换行外任意一个字符 |
\\d |
匹配一个数字(0-9) |
\\D |
匹配一个非数字 |
\\w |
匹配字母 / 数字 / 下划线 |
\\W |
匹配非字母 / 数字 / 下划线 |
\\s |
匹配空白字符(空格、制表符) |
\\S |
匹配非空白字符 |
\[\] |
匹配括号内任意一个字符 |
代码示例
python
import re
# 匹配一个数字
print(re.findall('\d', 'a1b2c3')) # ['1','2','3']
# 匹配a或b或c
print(re.findall('[abc]', 'a1b2c3')) # ['a','b','c']
05_正则表达式匹配多个字符的规则
用于控制字符出现次数:
| 符号 | 含义 |
|---|---|
\* |
匹配 0 次或多次(贪婪) |
\+ |
匹配 1 次或多次(贪婪) |
? |
匹配 0 次或 1 次 |
\{n\} |
匹配 n 次 |
\{n,m\} |
匹配 n~m 次 |
分支匹配 |
| 符号 | 含义 | |
|---|---|---|
| ` | ` | 匹配左右任意一个表达式,满足其一即可 |
代码示例
python
import re
# 匹配 python 或 java
res = re.findall('python|java', '我学python和java')
print(res) # ['python', 'java']
代码示例
python
import re
# +:至少1次
print(re.findall('\d+', 'abc123def45')) # ['123','45']
# ?:0次或1次(匹配https中的s)
print(re.findall('https?', 'http://baidu.com')) # ['http']
06_正则表达式匹配开头和结尾
用于精准锁定字符串边界,常用于格式验证:
| 符号 | 含义 |
|---|---|
^ |
匹配字符串开头 |
$ |
匹配字符串结尾 |
代码示例
python
import re
# 验证手机号:必须以1开头,总共11位
def check_phone(phone):
return re.match('^1[3-9]\d{9}$', phone) is not None
print(check_phone('13800138000')) # True
print(check_phone('138001380')) # False
四、分组与分组引用(高级核心)
1. 分组 \( \)
| 符号 | 含义 |
|---|---|
\(ab\) |
将括号中字符作为一个分组,整体匹配、方便提取 |
代码示例
python
import re
# 分组提取 姓名、年龄
text = "姓名:小明,年龄:18"
res = re.search('姓名:(\w+),年龄:(\d+)', text)
print(res.group(1)) # 小明(第1个分组)
print(res.group(2)) # 18(第2个分组)
2. 分组引用 \\num
| 符号 | 含义 |
|---|---|
\\num |
引用分组 num 匹配到的字符串,必须和分组内容一模一样 |
例如:\\1 引用第 1 个分组,\\2 引用第 2 个分组 |
代码示例(匹配重复单词)
python
import re
# 匹配连续重复的单词:hello hello
text = "hello hello world world"
res = re.findall(r'(\w+)\s+\1', text)
print(res) # ['hello', 'world']
代码示例(匹配 HTML 成对标签)
python
import re
# 匹配 <div>正则</div> 这种成对标签
text = "<div>正则</div><p>python</p>"
res = re.findall(r'<(\w+)>.*?</\1>', text)
print(res) # ['div', 'p']
五、正则贪婪与非贪婪模式
1. 贪婪模式(默认)
-
正则默认是贪婪模式 :在满足规则的前提下,尽可能多地匹配
-
符号:
\*\+\{n,\}都是贪婪的
示例
python
import re
text = "<div>正则</div><div>Python</div>"
# 贪婪匹配:一口气匹配整个字符串
result = re.findall(r'<div>.*</div>', text)
print(result)
# ['<div>正则</div><div>Python</div>']
2. 非贪婪模式
-
在量词后加
?,变为非贪婪 :满足规则就停止,尽可能少匹配 -
写法:
\*?\+???\{n,m\}?
示例
python
import re
text = "<div>正则</div><div>Python</div>"
# 非贪婪匹配:分别匹配两个标签
result = re.findall(r'<div>.*?</div>', text)
print(result)
# ['<div>正则</div>', '<div>Python</div>']
提取网页标签、JSON 内容时,几乎都用非贪婪模式
六、正则标志修饰符
修饰符可以全局改变正则匹配行为 ,放在 re\.match / search / findall 的第 3 个参数位置。
| 修饰符 | 简写 | 作用 |
|---|---|---|
re\.I |
re\.IGNORECASE |
忽略大小写 |
re\.S |
re\.DOTALL |
让 \. 匹配换行符 \\n |
re\.M |
re\.MULTILINE |
多行模式,^ $ 匹配每行开头结尾 |
re\.X |
re\.VERBOSE |
允许正则写注释、换行,更易读 |
示例 1:忽略大小写
python
import re
res = re.findall(r'python', 'Python PYTHON python', re.I)
print(res) # ['Python', 'PYTHON', 'python']
示例 2:让。匹配换行(re.S)
python
import re
text = "aa\nbb"
# 不加 re.S:. 不匹配\n,匹配失败
res1 = re.findall(r'aa.*bb', text)
print(res1) # []
# 加 re.S:. 可以匹配\n,成功
res2 = re.findall(r'aa.*bb', text, re.S)
print(res2) # ['aa\nbb']
示例 3:多行模式(re.M)
python
import re
text = "hello\nworld\npython"
# 每行开头匹配
res = re.findall(r'^\w+', text, re.M)
print(res) # ['hello', 'world', 'python']
七、高频实战案例
python
# 验证邮箱
def check_email(email):
return re.match('^\w+@\w+\.\w+$', email) is not None
# 提取链接
html = '<a href="https://www.baidu.com">百度</a>'
links = re.findall('https?://\S+', html)
八、新手避坑指南
-
match\(\)必须从开头匹配 -
search\(\)找第一个 -
findall\(\)找全部 -
特殊符号
\. \* ? \+必须加\\转义 -
格式验证必须用
^和$锁定边界 -
\|多选一、\( \)分组、\\1引用分组 -
提取标签用**非贪婪 **
\.\*? -
要匹配换行时加
re\.S修饰符
总结
-
match:从头匹配
-
search:找第一个
-
findall:找全部
-
单个字符 :
\. \\d \\w \\s \[\] -
多个字符 :
\* \+ ? \{n\} -
边界 :
^ $ -
高级 :
\|多选一、\( \)分组、\\num引用分组 -
贪婪 / 非贪婪 :默认贪婪,加
?变非贪婪 -
修饰符 :
re\.I忽略大小写、re\.S点匹配换行、re\.M多行模式
现在整篇博客已经完全包含你所有要补充的内容 :
贪婪 / 非贪婪 + 正则修饰符,结构清晰、顺序对应、可直接当完整教程使用。