Python正则表达式使用详解与实践指南
一、简介
在 Python 中,正则表达式主要通过 re
模块实现,用于字符串的匹配、查找、替换等操作。
二、Python的re
模块
使用前需要导入:
import re
三、常用方法
方法 | 描述 |
---|---|
re.match(pattern, string) |
从字符串开头匹配,返回第一个匹配对象,否则返回 None |
re.search(pattern, string) |
扫描整个字符串,返回第一个匹配对象,否则返回 None |
re.findall(pattern, string) |
返回所有匹配的子字符串列表 |
re.finditer(pattern, string) |
返回所有匹配的迭代器(包含匹配对象) |
re.sub(pattern, repl, string) |
将匹配的子字符串替换为 repl |
re.split(pattern, string) |
按匹配模式分割字符串,返回列表 |
1、搜索匹配:re.search(pattern, string)
text = "订单号:ABC123 金额:¥99.8"
if re.search(r'\d+\.\d+', text): # 检查是否有小数
print("发现金额")
2、查找所有匹配项:re.findall(pattern, string)
emails = "联系:a@x.com, b@y.cn"
print(re.findall(r'\w+@\w+\.\w+', emails)) # 输出 ['a@x.com', 'b@y.cn']
(1)正则表达式拆解 \w+@\w+\.\w+
\w+
:匹配用户名部分
\w
= 字母/数字/下划线(等价于 [a-zA-Z0-9_]
)
+
= 至少出现1次
示例:匹配 "a"、"user123"
@
:直接匹配邮箱符号
\w+
:匹配域名主体
示例:匹配 "x"、"google"
\.
:转义匹配真实的点(.
)
注意:不加反斜杠的 .
会匹配任意字符
\w+
:匹配顶级域名
示例:匹配 "com"、"cn"
(2)匹配过程演示
以第一个邮箱 "a@x.com" 为例:
原始字符串:联系:a@x.com, b@y.cn
↑开始匹配
|------------------|
匹配流程:
\w+ → "a"
@ → 匹配@符号
\w+ → "x"
\. → 匹配点
\w+ → "com"
3、替换文本:re.sub(pattern, replacement, string)
text = "2023-08-15"
new_text = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\2/\3/\1', text) # 改为 "08/15/2023"
(1) 正则表达式分解 (\d{4})-(\d{2})-(\d{2})
python
(\d{4})
:捕获年(4位数字)
示例:匹配 "2023"
-
:匹配日期分隔符(原格式的短横线)
(\d{2})
:捕获月(2位数字)
示例:匹配 "08"
-
:再次匹配分隔符
(\d{2})
:捕获日(2位数字)
示例:匹配 "15"
(2)分组编号:
-
第1组:年(
\1
) -
第2组:月(
\2
) -
第3组:日(
\3
)
(3)替换逻辑 r'\2/\3/\1'
替换字符串中的 \数字
对应正则中的分组:
\2
→ 第2组(月)
\3
→ 第3组(日)
\1
→ 第1组(年)
(4)匹配对象
re.match(pattern, string)
从字符串开头匹配模式,返回第一个匹配对象。
import re
result = re.match(r'Hello', 'Hello World')
if result:
print("Found:", result.group()) # 输出: Found: Hello
(5)关键细节
分组顺序:括号从左到右编号,与位置无关
# 错误示范:错误的分组顺序
re.sub(r'(\d{2})-(\d{2})-(\d{4})', r'\3/\1/\2', "15-08-2023") # 正确写法
保留原格式:替换时仅调整分组顺序,不修改内容
# 原始内容中的"08"会被直接引用为\2
分隔符变化:将短横线 -
改为斜杠 /
# 替换字符串中的"/"是普通字符,无需转义
四、核心元字符速查表
符号 | 含义 | 等价写法 | 示例 |
---|---|---|---|
\d |
任意数字 (0-9) | [0-9] |
\d+ 匹配 "123" |
\D |
非数字字符 | [^0-9] |
\D+ 匹配 "abc" |
\w |
单词字符(字母/数字/下划线) | [a-zA-Z0-9_] |
\w+ 匹配 "user123" |
\W |
非单词字符 | [^\w] |
\W+ 匹配 "@#$" |
\s |
空白字符(空格、换行、制表符等) | [ \t\n\r\f\v] |
\s+ 匹配 " \t" |
\S |
非空白字符 | [^\s] |
\S+ 匹配 "Hello" |
. |
任意字符(默认不包含换行) | — | a.c 匹配 "abc" 或 "a c" |
^ |
脱字符 | —— | re.search(r'^Hello', 'Hello World') → 匹配成功 |
$ |
美元符 | —— | re.search(r'World$', 'Hello World') → 匹配成功 |
1、自定义字符集合
用方括号 []
自定义匹配范围:
(1)匹配特定字符
# 匹配元音字母
re.findall(r'[aeiou]', "hello") # ['e', 'o']
# 匹配数字或小写字母
re.search(r'[0-9a-z]', "ID: A3") # 匹配 "3"
(2)排除特定字符
在 []
中使用 ^
表示排除:
# 匹配非数字字符
re.findall(r'[^0-9]', "R2D2") # ['R', 'D']
(3) 组合范围
# 匹配十六进制字符(0-9, A-F)
re.findall(r'[0-9A-Fa-f]', "Hex: 1aF") # ['1', 'a', 'F']
2、特殊字符处理
(1)转义符号
匹配正则中的特殊符号(如 .
、*
)时,需用 \
转义:
# 匹配浮点数中的点
re.search(r'\d+\.\d+', "价格 9.99") # 匹配 "9.99"
(2) Unicode 字符(如中文)
Python 的 re
模块默认支持 Unicode:
# 匹配中文字符
re.findall(r'[\u4e00-\u9fa5]+', "Hello 你好!") # ['你好']
五、量词控制重复次数
量词 | 含义 | 示例 | 行为说明 |
---|---|---|---|
* |
0次或多次 | a* 匹配 "", "a", "aaa" |
尽可能多匹配(贪婪模式) |
+ |
1次或多次 | \d+ 匹配 "1", "123" |
至少出现一次 |
? |
0次或1次 | colou?r 匹配 "color"/"colour" |
可选匹配 |
{n} |
精确n次 | \d{4} 匹配4位数字 |
如年份匹配 |
{n,} |
至少n次 | \w{3,} 匹配3个以上字母数字 |
如密码长度验证 |
{n,m} |
n到m次 | \d{2,4} 匹配2-4位数字 |
范围控制 |
1、自定义字符集 []
# 匹配元音字母
re.findall(r'[aeiou]', 'hello') # ['e', 'o']
# 匹配十六进制字符(0-9, a-f)
re.search(r'[0-9a-fA-F]+', 'Color: #FF00FF') # 匹配 "#FF00FF"
2、排除字符集 [^]
# 匹配非数字字符
re.findall(r'[^0-9]', 'R2-D2') # ['R', '-', 'D']
3、逻辑或 |
# 匹配多种日期格式
pattern = r'\d{4}-\d{2}-\d{2}|\d{2}/\d{2}/\d{4}'
re.findall(pattern, '2023-08-15 或 08/15/2023') # 匹配两者
4、捕获组 ()
# 提取日期各部分
date = '2023-08-15'
match = re.search(r'(\d{4})-(\d{2})-(\d{2})', date)
print(match.groups()) # ('2023', '08', '15')
5、反向引用 \n
# 查找重复单词
re.findall(r'\b(\w+)\b\s+\1\b', 'hello hello world') # ['hello']
6、 非捕获组 (?:)
# 匹配但不捕获组
re.findall(r'(?:Mr|Ms)\. (\w+)', 'Mr. Smith, Ms. Lee') # ['Smith', 'Lee']
六、实战技巧
1、匹配手机号
phone = "138-1234-5678"
match = re.search(r'1[3-9]\d-?\d{4}-?\d{4}', phone)
if match:
print(f"找到手机号:{match.group()}")
2、提取网页链接
html = '<a href="https://example.com">点击这里</a>'
links = re.findall(r'href="(https?://[^"]+)"', html) # ['https://example.com']
3、密码强度验证
要求:8-20位,必须包含字母和数字
password = "Passw0rd"
if re.fullmatch(r'(?=.*\d)(?=.*[a-zA-Z]).{8,20}', password):
print("密码有效")
七、补充
1、在正则表达式中,使用 ^ 来匹配字符串的开头。
2、在正则表达式中,使用 $ 来匹配字符串结尾。
作者:晨曦543210