【Python进阶】Python正则表达式:5分钟掌握字符串匹配黑魔法,效率提升100%!

各位小伙伴好,我是唐叔!今天咱们来聊聊Python中的正则表达式——这个让无数程序员又爱又恨的"黑魔法"。正则表达式就像是一把瑞士军刀,能轻松解决字符串匹配、提取、替换等复杂问题。别被它的语法吓到,跟着唐叔学,5分钟就能上手!

一、正则表达式是啥?为啥要用它?

一句话解释:正则表达式(Regular Expression,简称regex)就是用来匹配字符串的规则。比如:

  • 检查手机号格式是否正确
  • 从网页源码中提取所有链接
  • 批量替换文本中的敏感词

不用正则的痛

# 判断手机号是否合法(11位数字)
phone = "13800138000"
if len(phone) == 11 and phone.isdigit():
    print("合法")
else:
    print("不合法")

用正则的爽

import re
phone = "13800138000"
if re.match(r"^\d{11}$", phone):
    print("合法")
else:
    print("不合法")

二、5大核心操作,快速上手正则

1. 匹配:re.match() vs re.search()

  • match():从字符串开头匹配
  • search():在字符串中搜索匹配
import re

# match示例
text = "Python is awesome"
print(re.match(r"Python", text))  # 匹配成功
print(re.match(r"awesome", text)) # 匹配失败(因为不是开头)

# search示例
print(re.search(r"awesome", text)) # 匹配成功

记忆口诀match看开头,search随便搜!

2. 查找所有:re.findall()

提取字符串中所有符合规则的子串:

text = "我的电话是13800138000,你的电话是13912345678"
phones = re.findall(r"\d{11}", text)
print(phones)  # 输出: ['13800138000', '13912345678']

记忆口诀findall全抓取,返回列表不用愁!

3. 替换:re.sub()

批量替换字符串中的内容:

text = "Python是最好的语言!Java也是最好的语言!"
new_text = re.sub(r"最好的语言", "yyds", text)
print(new_text)  # 输出: Python是yyds!Java也是yyds!

记忆口诀sub替换忙,一键全改光!

4. 分割:re.split()

按规则切割字符串:

text = "Python,Java;C++|JavaScript"
langs = re.split(r"[,;|]", text)
print(langs)  # 输出: ['Python', 'Java', 'C++', 'JavaScript']

记忆口诀split切割忙,规则随便放!

5. 分组提取:()

用括号分组,提取特定部分:

text = "姓名: 唐叔, 年龄: 18"
match = re.search(r"姓名: (\w+), 年龄: (\d+)", text)
if match:
    print(f"姓名: {match.group(1)}, 年龄: {match.group(2)}")
# 输出: 姓名: 唐叔, 年龄: 18

记忆口诀:括号来分组,group轻松取!

三、正则表达式语法速记表

符号含义示例
\d匹配数字\d{3}匹配3位数字
\w匹配字母数字\w+匹配一个单词
.匹配任意字符a.b匹配a和b之间的任意字符
*匹配0次或多次a*匹配0个或多个a
+匹配1次或多次a+匹配1个或多个a
?匹配0次或1次a?匹配0个或1个a
{n}匹配n次\d{4}匹配4位数字
[]匹配括号内任意字符[abc]匹配a、b或c

记忆口诀

  • \d是数字,\w是字母
  • .是任意,*是0到多
  • +是1到多,?是0或1
  • {n}是固定次数,[]是选一个

四、如何高效自定义正则表达式

正则表达式的强大之处在于它的灵活性,但如何高效地自定义正则表达式呢?唐叔教你几招!

1. 明确需求,分步构建

不要试图一次性写出完美的正则表达式,先分解需求,逐步构建。
示例:匹配一个合法的日期格式(YYYY-MM-DD)

  • 第一步:匹配4位年份 \d{4}
  • 第二步:匹配分隔符 -
  • 第三步:匹配2位月份 \d{2}
  • 第四步:匹配2位日期 \d{2}
  • 最终组合:\d{4}-\d{2}-\d{2}

2. 使用在线工具调试

推荐使用在线正则表达式调试工具,如 regex101regexrdebuggex,实时查看匹配结果。

当然如果使用VS Code进行开发,也可以考虑使用VS Code插件:Regex Previewer或RegExp Explain。

3. 避免贪婪匹配

默认情况下,正则表达式是贪婪的(尽可能多匹配),可以通过?改为非贪婪模式。
示例

text = "<div>Python</div><div>Java</div>"
print(re.findall(r"<div>(.*)</div>", text))  # 贪婪:['Python</div><div>Java']
print(re.findall(r"<div>(.*?)</div>", text)) # 非贪婪:['Python', 'Java']

4. 合理使用分组

分组不仅可以提取数据,还能让正则表达式更清晰。
示例:提取URL中的协议和域名

url = "https://www.csdn.net"
match = re.match(r"(https?)://([^/]+)", url)
if match:
    print(f"协议: {match.group(1)}, 域名: {match.group(2)}")
# 输出: 协议: https, 域名: www.csdn.net

5. 预编译正则表达式

如果需要多次使用同一个正则表达式,可以使用re.compile()预编译,提升效率。
示例

pattern = re.compile(r"\d{11}")
print(pattern.match("13800138000"))  # 匹配成功

五、避坑指南

  1. 贪婪匹配:默认是贪婪模式(尽可能多匹配),加?变非贪婪
text = "<div>Python</div><div>Java</div>"
print(re.findall(r"<div>(.*)</div>", text))  # 贪婪:['Python</div><div>Java']
print(re.findall(r"<div>(.*?)</div>", text)) # 非贪婪:['Python', 'Java']
  1. 原始字符串:正则表达式前加r,避免转义字符问题
# 错误写法
re.match("\d", "123")  # 报错
# 正确写法
re.match(r"\d", "123")  # 匹配成功

六、实战案例:提取邮箱地址

需求:从一段文本中提取所有合法的邮箱地址。

import re

text = """
联系我们:
客服邮箱:support@csdn.net
投诉邮箱:feedback@csdn.com
无效邮箱:admin@localhost
"""

# 定义邮箱正则规则
email_pattern = r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"

# 提取邮箱
emails = re.findall(email_pattern, text)
print("提取到的邮箱地址:", emails)

输出结果

提取到的邮箱地址: ['support@csdn.net', 'feedback@csdn.com']

唐叔总结

正则表达式就像是一把万能钥匙,能打开字符串处理的各种难题。今天咱们从匹配、查找、替换、分割到分组提取,一步步拆解了正则的核心操作。

当然也需要注意,正则表达式就像一把双刃剑

  • 用得好:代码简洁高效,老板直呼内行
  • 用不好:同事看到你的正则,连夜提交离职申请

需要牢记:

  1. 复杂正则要写注释
  2. 超过3行的正则,就该考虑换方法了
  3. 能用字符串方法解决的,别用正则(比如str.replace())

附录:常见正则表达式示例

以下是常见的正则表达式使用场景及其对应的正则规则,帮助大家快速上手:

场景描述正则表达式示例代码示例
匹配手机号^\d{11}$re.match(r"^\d{11}$", "13800138000")
匹配邮箱地址\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\bre.findall(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b", text)
匹配URLhttps?://[^\s]+re.findall(r"https?://[^\s]+", "Visit https://csdn.net for more info")
匹配IP地址\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\bre.match(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", "192.168.1.1")
匹配日期(YYYY-MM-DD)\d{4}-\d{2}-\d{2}re.findall(r"\d{4}-\d{2}-\d{2}", "会议时间:2023-10-01")
匹配中文[\u4e00-\u9fa5]re.findall(r"[\u4e00-\u9fa5]", "Python真香!")
匹配HTML标签<[^>]+>re.findall(r"<[^>]+>", "<div>Python</div>")
匹配空白行^\s*$re.findall(r"^\s*$", " \n ")
匹配密码强度(至少8位,包含大小写字母和数字)^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$re.match(r"^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$", "Passw0rd")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值