Python 正则表达式详解与实战案例
前言
正则表达式(Regular Expression)在网络爬虫、数据分析、文本处理等领域有着广泛的应用。掌握正则表达式能够达到事半功倍的效果,是程序员必备的技能之一。本文详细介绍正则表达式中各种规则及其符号含义,并结合 Python 中的 库进行演示,由浅入深,即学即练即用。
Python 正则表达式的基础概念、语法规则及实际应用。内容涵盖普通字符、转义字符、限定符、分组、锚点等核心规则,深入解析了贪婪与非贪婪匹配模式。重点讲解了 Python 标准库 re 的主要函数(match, search, findall, sub 等)及常用标志位。文章提供了用户名验证、邮箱提取、手机号格式化、数据清洗等多个实战代码案例,并给出了性能优化与可读性的最佳实践建议,旨在帮助开发者掌握正则表达式技能以提升文本处理效率。

正则表达式(Regular Expression)在网络爬虫、数据分析、文本处理等领域有着广泛的应用。掌握正则表达式能够达到事半功倍的效果,是程序员必备的技能之一。本文详细介绍正则表达式中各种规则及其符号含义,并结合 Python 中的 库进行演示,由浅入深,即学即练即用。
re正则表达式就是用一组由字母和符号组成的'表达式'来描述一个特征,然后去验证另一个'字符串'是否符合这个特征。比如表达式 xy+ 描述的特征是'一个 'x' 和至少一个 'y'',那么 xy, xyy, xyyyyyyy 都符合这个特征。
字母、数字、汉字、下划线、以及没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。
例 1:表达式
c,在匹配字符串abcde时,匹配结果是:成功;匹配到的内容是:c;匹配到的位置是:开始于 2,结束于 3。(包含开始位置,不包含结束位置)
例 2:表达式
bcd,在匹配字符串abcde时,匹配结果是:成功;匹配到的内容是:bcd;匹配到的位置是:开始于 1,结束于 4。
一些不便书写的字符,采用在前面加 \ 的方法。例如制表符、换行符等;
一些有特殊用处的标点符号,在前面加 \ 后,代表该符号本身。例如 {,}, \[, \], /, \\, +, *, ., $, ^, |, ? 等;
转义字符的匹配方法与'普通字符'类似,也是匹配与之相同的一个字符。
例如:表达式
\d,在匹配字符串abcde时,匹配结果是:失败(因为 d 不是数字)。如果字符串是a1cde,则匹配成功,匹配到1。
正则表达式中的一些表示方法,可以匹配'多种字符'中的任意一个字符。例如,表达式 \d 可以匹配任意一个数字。虽然可以匹配其中任意字符,但是只能是一个,不是多个。
例如:表达式
\d\d,在匹配abc123时,匹配的结果是:成功;匹配到的内容是:12;匹配到的位置是:开始于 3,结束于 5。
使用方括号 [] 包含一系列字符,能匹配其中任意一个字符。用 [^] 包含一系列字符,则能匹配其中字符之外的任意一个字符。虽然可以匹配其中任意一个,但是只能是一个,不是多个。
例如:表达式
[bcd][bcd]匹配abc123时,匹配的结果是:成功;匹配到的内容是:bc;匹配到的位置是:开始于 1,结束于 3。
这些符号用于指定前面的字符或组需要匹配的次数:
*:匹配前一个字符 0 次或多次。+:匹配前一个字符 1 次或多次。?:匹配前一个字符 0 次或 1 次。{n}:匹配前一个字符恰好 n 次。{n,}:匹配前一个字符至少 n 次。{n,m}:匹配前一个字符至少 n 次,至多 m 次。例如:表达式
\d+\.?\d*在匹配It costs $12.5时,匹配的结果是:成功;匹配到的内容是:12.5;匹配到的位置是:开始于 10,结束于 14。
^:匹配字符串的开始位置。$:匹配字符串的结束位置。|:表示'或',匹配左边或右边的表达式。():分组,将多个字符视为一个整体。\s:匹配空白字符(空格、制表符、换行等)。例 1:表达式
^aaa在匹配xxxaaaxxx时,匹配失败。因为^要求与字符串开始的地方匹配,只有当aaa位于字符串的开头的时候,^aaa才能匹配,比如:aaaxxxxxx。
例 2:表达式
aaa$在匹配xxxaaaxxx时,匹配失败。因为$要求与字符串结束的地方匹配,只有当aaa位于字符串的结尾的时候,aaa$才能匹配,比如:xxxxxxaaa。
例 3:表达式
Tom|Jack在匹配字符串I'm Tom, he is Jack时,匹配结果是:成功;匹配到的内容是:Tom;匹配下一个时,匹配结果是:成功;匹配到的内容是:Jack。
例 4:表达式
(go\s*)+在匹配Let's go gogo!时,匹配结果是:成功;匹配到内容是:gogogo;匹配到的位置是:开始于 6,结束于 14。
例 5:表达式
¥(\d+\.?\d*)在匹配$10.9,¥20.5时,匹配的结果是:成功;匹配到的内容是:¥20.5;匹配到的位置是:开始于 6,结束于 10。单独获取括号范围匹配到的内容是:20.5。
请尝试写出满足下列要求的正则表达式:
在使用修饰匹配次数的特殊符号时,如 ?, *, + 等,可以使同一个表达式能够匹配不同的次数,具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配,这种匹配原则就叫作"贪婪"模式。
例如,针对文本 dxxxdxxxd,表达式 d.*d 会匹配从第一个 d 到最后一个 d 之间的所有内容,即 dxxxdxxxd。
在修饰匹配次数的特殊符号后再加上一个 ? 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的'不匹配'。这种匹配原则叫作"非贪婪"模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。
例如,针对文本 dxxxdxxxd,表达式 d.*?d 会匹配 dxxx(第一个 d 到第二个 d)。
re 库是 Python 的标准库,不需要额外安装,主要用于字符串匹配。
import re
re 库采用 raw string 类型表示正则表达式,rawstring 是不包含对转义符再次转义的字符串。例如:r'[1-9]\d{5}'。
re 库也可以采用 string 类型表示正则表达式,但更繁琐,例如:'[1-9]\\d{5}'。
当正则表达式包含转义符时,建议使用 raw string。
注意 group() 和 groups() 的区别,一个是返回匹配的字符串,一个是返回各部分匹配内容组成的元组。当表达式中没有圆括号时,groups() 返回的是空元组,当存在圆括号时,有几个圆括号 groups() 返回的元组里就有几个元素。
re.I (IGNORECASE):忽略大小写。re.M (MULTILINE):多行模式,改变 ^ 和 $ 的行为。re.S (DOTALL):点号匹配包括换行符在内的所有字符。re.X (VERBOSE):允许注释和空白,提高可读性。编写程序实现下述功能,提示用户输入用户名,要求用户名以字母开头,长度不少于 3 位,只能包含字母、数字、下划线,如果用户输入符合要求,则提示注册成功,否则提示用户名不符合要求,请重新输入,一直循环直到用户名符合要求为止。
参考代码如下:
import re
name = input("请输入用户名,以字母开头,长度不少于 3 位,只能包含字母、数字、下划线:")
# 正则解释:^ 开头,[a-zA-Z] 首字母,\w{2,} 后续至少 2 个字符,$ 结尾
match = re.match(r"^[a-zA-Z]\w{2,}$", name)
while match is None:
print("用户名不符合要求,请重新输入:", end=" ")
name = input()
match = re.match(r"^[a-zA-Z]\w{2,}$", name)
print("恭喜你,{},注册成功!".format(name))
从一段文本中提取所有的邮箱地址。
import re
text = "联系邮箱:[email protected] 或 [email protected]"
pattern = r"[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+"
emails = re.findall(pattern, text)
for email in emails:
print(email)
验证并格式化中国大陆手机号码。
import re
phone = "13812345678"
# 标准手机号格式:1 开头,第二位 3-9,后面 9 位数字
pattern = r"^1[3-9]\d{9}$"
if re.match(pattern, phone):
# 格式化输出:138 1234 5678
formatted = re.sub(r"(\d{3})(\d{4})(\d{4})", r"\1 \2 \3", phone)
print(f"有效手机号:{formatted}")
else:
print("无效手机号")
将文本中的敏感词替换为星号。
import re
text = "这是一个测试文本,包含关键词:隐私、机密、秘密。"
# 使用 sub 进行替换
result = re.sub(r"隐私 | 机密 | 秘密", "***", text)
print(result)
假设有一个包含编程语言排名的 HTML 片段,我们需要提取名称和排名。
import re
html_content = "<div class='rank'>1. Python</div><div class='rank'>2. Java</div>"
pattern = r"class='rank'>(\d+)\.\s*(.+?)</div>"
matches = re.findall(pattern, html_content)
for rank, lang in matches:
print(f"Rank {rank}: {lang}")
re.compile() 预编译。re.VERBOSE 标志,允许在正则中加入注释和换行,便于维护。*? 或 +? 防止匹配过多内容导致性能下降或逻辑错误。^ 和 $ 确保匹配的是完整字段而非部分字段。正则表达式是处理文本的强大工具。通过理解基本规则、掌握 Python re 模块的常用函数,并结合实际场景进行练习,可以高效地完成各种文本处理任务。希望本文的内容能帮助初学者快速入门并应用于实际开发中。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online