欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > Python入门教程丨3.5 正则表达式

Python入门教程丨3.5 正则表达式

2025/2/24 14:24:52 来源:https://blog.csdn.net/w646645452/article/details/145807125  浏览:    关键词:Python入门教程丨3.5 正则表达式

今天我们来学习 Python 里超实用的字符串匹配和正则表达式。这是处理文本数据的神器,无论是爬虫、数据清洗还是文本分析,都离不开它,我们从基础语法讲起,再到实战场景,深入体会正则的妙用。

1. re 库

正则表达式(Regular Expression,简称regex或regexp)是一种用来匹配字符串的强大工具。它由一串字符和特殊符号组成,用于描述或匹配一系列符合某种模式的字符串。正则表达式广泛应用于文本搜索、文本替换等操作中。Python中的re模块提供了对正则表达式的全面支持。

1.1 正则表达式基础语法

1.1.1 正则表达式基本元素
符号描述示例
.匹配除换行符外的任意字符a.c 可匹配 “abc”, “a1c” 等
^匹配字符串的开始^hello 匹配以 “hello” 开始的字符串
$匹配字符串的结束world$ 匹配以 “world” 结束的字符串
*匹配前面子表达式 0 次或多次ab*c 匹配 “ac”, “abc”, “abbc” 等
+匹配前面子表达式 1 次或多次ab+c 匹配 “abc”, “abbc” 等,但不匹配 “ac”
?匹配前面子表达式 0 次或 1 次colou?r 匹配 “color” 或 “colour”

.用来匹配除换行符外的任意字符

import re# 示例:匹配号码格式的字符串
text = "我的号码是 A123-456 和 B789+012"
pattern = r"A1..-4.."
match = re.search(pattern, text)
print(match.group())  # 输出:A123-456
# 这里的 "A1..-4.." 中的每 “.” 都匹配一个字符,就像“万能胶” 

^匹配字符串的开始

import re# 示例:检查用户名是否以特定前缀开头
text = "user12345"
pattern = r"^user"  # 匹配以 "user" 开头的字符串
match = re.search(pattern, text)
print("用户名以 'user' 开头:", bool(match))

$匹配字符串的结束

import re# 示例:检查一段话是否以问句结束
text = "这是为什么呢?"
pattern = r"呢?$"  # 匹配以 "呢?" 结尾的字符串
match = re.search(pattern, text)
print("句子以 '呢?' 结尾:", bool(match))

*匹配前面子表达式 0 次或多次

import re# 示例:匹配某人吃了多少块披萨
text = "他吃了披萨pizza, pppppizza, 和 pizza!"
pattern = r"p*izza"  # 匹配 "pizza" 或 "pppppizza" 等
matches = re.findall(pattern, text)
print(matches)  # 输出:['pizza', 'pppppizza', 'pizza']

+匹配前面子表达式 1 次或多次

import re# 示例:匹配某人的电子邮件地址是否包含至少一个 @
text = "我的邮箱是 test@domain.com 和 another@test.com"
pattern = r"\w+@\w+\.\w+"  # 匹配包含至少一个 "@" 的邮箱地址
matches = re.findall(pattern, text)
print(matches)  # 输出:['test@domain.com', 'another@test.com']

?匹配前面子表达式 0 次或 1 次


1.1.2. 特殊字符集
符号描述示例
\d匹配一个数字字符\d\d\d-\d\d\d-\d\d\d\d 匹配电话号码格式
\D匹配非数字字符\D{3} 匹配三个非数字字符
\w匹配字母、数字或下划线\w+ 匹配单词
\W匹配非字母、数字或下划线\W+ 匹配非单词字符
\s匹配任何空白字符\s+ 匹配空格、制表符等

\d用来匹配一个数字字符

import re
text = "我有6颗苹果!"
pattern = r"我有 \d+ 颗苹果"  # 匹配以数字表示的苹果数量
print(re.findall(pattern, text))  # 输出:['我有6颗苹果']

\D匹配非数字字符

import re
text = "这是一段没有数字的文字!"
pattern = r"\D+"  # 匹配所有非数字字符
print(re.findall(pattern, text))  # 输出:['这是一段没有数字的文字!\n']
# 这里非数字字符的范围很广,包括了字母和标点

\w匹配字母、数字或下划线

import re
text = "我的用户名是_user123"
pattern = r"\w+"  # 匹配用户名中的字母、数字和下划线
print(re.findall(pattern, text))  # 输出:['我的用户名是', '_user123']

\W匹配非字母、数字或下划线,即匹配特殊字符

import re
text = "这是一段$带有特殊字符的文本!@#"
pattern = r"\W+"  # 匹配所有非字母、数字或下划线的字符
print(re.findall(pattern, text))  # 输出:['$', '!', '@#']

\s匹配任何空白字符

import re
text = "这是 一段有 多余空格 的 文本。"
pattern = r"\s+"  # 匹配文本中的所有空白字符
print(re.findall(pattern, text))  # 输出:[' ', ' ', ' ', ' ']

1.2 re模块常用函数

函数用法示例
search()扫描整个字符串并返回第一个成功的匹配re.search(r'ain', 'The rain in Spain')
match()尝试从字符串的起始位置匹配一个模式re.match(r'The', 'The rain in Spain')
findall()返回所有与模式匹配的列表re.findall(r'ain', 'The rain in Spain')
sub()替换所有匹配项为指定字符串re.sub(r'Spain', 'France', 'The rain in Spain')
split()根据模式分割字符串re.split(r'\s+', 'The rain in Spain')

re.search() 用于在字符串中寻找第一个匹配的模式。如果找到匹配,返回一个匹配对象,否则返回 None

import re
text = "Hello, World!"
pattern = r"World"
result = re.search(pattern, text)
if result:print("匹配成功!")print("匹配位置:", result.start(), result.end())
else:print("匹配失败!")
# 匹配成功!匹配位置: 7 12

re.findall() 用于找到字符串中所有匹配的模式,返回一个列表。

import re
text = "I have 1 apple, 2 bananas, and 3 oranges"
pattern = r"\d+"
result = re.findall(pattern, text)
print(result)  # 输出:['1', '2', '3']

re.sub() 用于替换字符串中匹配的模式。它会将所有匹配的内容替换为指定的字符串。

import re
text = "I have 1 apple, 2 bananas, and 3 oranges"
pattern = r"\d+"
replacement = "many"
result = re.sub(pattern, replacement, text)
print(result)  # 输出:I have many apple, many bananas, and many oranges

re.match() 专门用来匹配字符串开头的部分,如果字符串的开头符合给定的模式,它会返回一个匹配对象;否则返回 None

import re# 示例:检查字符串是否以数字开头
text = "123 是一个数字"
pattern = r"\d+"  # 匹配一个或多个数字
# 使用 re.match()
result = re.match(pattern, text)
if result:print("匹配成功!匹配的内容是:", result.group())
else:print("匹配失败!")
#运行结果:匹配成功!匹配的内容是: 123

re.split() 可以根据指定的正则表达式模式将字符串分割成多个部分,并返回一个列表。

import re# 示例:按逗号或空格分割字符串
text = "apple, banana orange,grape"
pattern = r"[,\s]+"  # 匹配逗号或空格
# 使用 re.split()
result = re.split(pattern, text)
print("分割后的结果:", result)
# 分割后的结果: ['apple', 'banana', 'orange', 'grape']

1.3 复杂模式

正则表达式不仅能匹配单个字符,还能通过一些特殊符号和语法构建复杂的匹配模式。下面我们来介绍几个常用的复杂模式构建方法。

符号用法示例
{n}匹配前一字符恰好 n 次a{2} 匹配 “aa”
{n,}至少匹配 n 次a{2,} 匹配 “aa”, “aaa” 等
{n,m}最少匹配 n 次且最多 m 次a{2,3} 匹配 “aa”, “aaa”
[abc]字符集合,匹配括号内任一字符[abc] 匹配 “a”, “b”, 或 “c”

{n}:该模式表示前一个字符必须出现恰好 n 次。

import re# 示例:匹配恰好 4 个连续的 'a'
text = "aaaa"
pattern = r"a{4}"
match = re.match(pattern, text)
print(match.group() if match else "No match")  # 输出:aaaa

{n,}:至少匹配 n 次,该模式表示前一个字符至少出现 n 次,可以无限次。

import re# 示例:匹配至少 2 个连续的 'a'
text = "aaaaaaaaaaa"
pattern = r"a{2,}"
match = re.match(pattern, text)
print(match.group() if match else "No match")  # 输出:aaaaaaaaaaa

{n,m}:该模式表示前一个字符至少出现 n 次,但不超过 m 次。

import re# 示例:匹配 1 到 3 个连续的 'a'
text = "aaabb"
pattern = r"a{1,3}"
match = re.match(pattern, text)
print(match.group() if match else "No match")  # 输出:aaa

[abc]:该模式表示匹配括号内的任一字符。

import re# 示例:匹配 'a' 或 'b' 或 'c'
text = "apple"
pattern = r"[abc]"
match = re.search(pattern, text)
print(match.group() if match else "No match")  # 输出:a

🎯Tips:

对于非常复杂的模式,建议分步骤构建并测试每个部分,想一口吃撑胖子很容易出错,分而治之是很好的思想。


1.4 贪婪与非贪婪模式

正则表达式中的贪婪模式和非贪婪模式是两种不同的匹配方式。在贪婪模式下,匹配尽可能多的字符,而非贪婪模式则匹配尽可能少的字符。

例如,对于字符串 “aaaab”,模式 “a+”(贪婪)将匹配整个 “aaaa”,而 “a+?”(非贪婪)将每次匹配一个 “a”。

1.4.1 贪婪模式

默认情况下,正则表达式的量词(如 *, +, ?, {n,}, {n,m})都是贪婪的,会尽可能多地匹配字符。

import retext = "abbbc"
pattern = r"ab+"  # 贪婪模式,匹配尽可能多的 b
match = re.search(pattern, text)
print(match.group())  # 输出:abbb
# 这里的正则表达式会匹配尽可能多的 'b',因为它是贪婪的。
1.4.2 非贪婪模式

在量词后加上问号?,即可启用非贪婪模式,匹配尽可能少的字符。

import retext = "abbbc"
pattern = r"ab+?"  # 非贪婪模式,匹配尽可能少的 b
match = re.search(pattern, text)
print(match.group())  # 输出:ab
# 这里的正则表达式会匹配最少的 'b',即只匹配一个 'b'。

在实际使用中,我们通常:

  • 使用 * 等贪婪匹配来处理简单的字符串操作。
  • 当需要精确控制匹配范围时,使用非贪婪模式来避免过度匹配。

例如我们在匹配网页源码时,匹配标签中的内容:

text = "I have <div>Hello, <span>World!</span></div>"
pattern_greedy = r"<.*>"
pattern_non_greedy = r"<.*?>"result_greedy = re.findall(pattern_greedy, text)
result_non_greedy = re.findall(pattern_non_greedy, text)print("贪婪匹配结果:", result_greedy)  # 输出:['<div>Hello, <span>World!</span></div>']
print("非贪婪匹配结果:", result_non_greedy)  # 输出:['<div>', '<span>']

2. 实际应用

2.1 邮箱/手机号格式验证

在用户注册或数据输入时,验证邮箱和手机号的格式是非常重要的。我们可以用正则表达式来实现。

(1)邮箱验证📧

import redef validate_email(email):pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"if re.match(pattern, email):return Trueelse:return Falseemail = "test@exa@mple.com"
if validate_email(email):print("邮箱格式正确!")
else:print("邮箱格式错误!")

(2)手机号验证📱

import re
def validate_phone(phone):pattern = r"^1[3-9]\d{9}$"if re.match(pattern, phone):return Trueelse:return Falsephone = "13812345678"
if validate_phone(phone):print("手机号格式正确!")
else:print("手机号格式错误!")

(3)手机号提取📱

import re
phone_pattern = r"(?<!\d)(1[3-9]\d{9})(?!\d)"
text = "紧急联系13812345678,备用19198765432"
phones = re.findall(phone_pattern, text)
print("提取到的手机号:", phones)  
#提取到的手机号: ['13812345678', '19198765432']

2.2 HTML 文件解析

在爬虫或数据提取中,经常需要从 HTML 中提取内容。正则表达式可以帮助我们快速提取标签中的内容。

import rehtml = """
<div class='news'><h1>今日热榜</h1><p>Python 3.12发布啦!</p>
</div>
"""# 提取所有标签内容
contents = re.findall(r"<.*?>(.*?)</.*?>", html)
print("HTML内容提取:", contents)  # ['今日热榜', 'Python 3.12发布啦!']# 提取指定标签内容
h1_content = re.search(r"<h1>(.*?)</h1>", html).group(1)
print("头条标题:", h1_content)  # 今日热榜

2.3 日志分析

在处理日志文件时,我们可能需要提取错误信息。正则表达式可以帮助我们快速过滤出错误信息。

log = """
[ERROR] 2023-08-10 14:22:35 数据库连接失败
[INFO] 2023-08-10 14:23:10 用户登录成功
[WARNING] 2023-08-10 14:24:02 内存使用率80%
"""# 提取错误信息
errors = re.findall(r"\[ERROR\].+", log)
print("系统错误记录:", errors)  # ['[ERROR] 2023-08-10 14:22:35 数据库连接失败']

2.4 综合案例:简历解析

我们有一个简历文本,现在要使用正则提取其中的主要信息,保存到 json 中。

完整代码:

import reresume = """
姓名:张三
电话:138-1234-5678
邮箱:zhangsan@example.com
技能:Python, 正则表达式, 数据分析项目经验:
1. <项目名称>智能客服系统</项目名称><描述>使用正则表达式实现对话指令解析</描述>
2. <项目名称>日志分析平台</项目名称><描述>开发基于正则的日志过滤模块</描述>
"""# 信息提取
def parse_resume(text):info = {"name": re.search(r"姓名:(.*)", text).group(1),"phone": re.search(r"电话:(.*)", text).group(1),"email": re.search(r"邮箱:(.*)", text).group(1),"skills": re.findall(r"技能:(.+)", text)[0].split(", "),"projects": re.findall(r"<项目名称>(.*?)</项目名称>\s+<描述>(.*?)</描述>", text)}return infoprint(parse_resume(resume))

运行结果:

{'name': '张三', 'phone': '138-1234-5678', 'email': 'zhangsan@example.com', 'skills': ['Python', '正则表达式', '数据分析'], 'projects': [('智能客服系统', '使用正则表达式实现对话指令解析'), ('日志分析平台', '开发基于正则的日志过滤模块')]}

3. 辅助开发工具

在学习和使用正则表达式时,可以使用在线测试工具,如 regex101.com。它支持多种编程语言的正则表达式测试,还能提供详细的匹配结果和解释,非常方便。

🔧 RegEx 调试神器地址: regex101.com

  • 实时高亮匹配 → 高亮匹配结果
  • 解释模式 → 自动翻译正则语法
  • 测试用例库 → 自带常见场景用例


4. 小结

正则表达式是文本处理的强大工具,掌握了它,你就能轻松应对各种文本匹配和提取任务。在学习正则表达式的过程中,需要注意以下几点:

理解元字符的含义 :元字符是正则表达式的核心,需要熟练掌握各个元字符的含义和用法,如 .^$*+? 等。

注意特殊字符的转义 :在正则表达式中,一些特殊字符如 .*+ 等具有特殊含义,如果需要匹配这些字符本身,需要进行转义,即在字符前加上反斜杠 \

掌握常用函数的用法re 模块提供了许多常用的函数,如 search()match()findall()sub()split() 等,需要熟练掌握这些函数的用法和区别。

理解贪婪与非贪婪模式 :贪婪模式会尽可能多地匹配字符,而非贪婪模式则尽可能少地匹配字符。在实际应用中,需要根据具体需求选择合适的模式。

注意调试和优化 :在编写复杂的正则表达式时,要注意调试和优化,避免出现错误和性能问题。可以使用在线测试工具如 regex101.com 进行调试和测试。

多多练习,熟练掌握正则表达式,人人都能成为文本处理的高手!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词