当前位置: 首页 > backend >正文

Python3正则表达式:字符串魔法师的指南[特殊字符]‍♂️

Python3正则表达式

    • 什么是正则表达式?
    • 在Python中使用正则表达式
    • 一、正则表达式基础语法:你的魔法咒语
      • 基本匹配符
      • 字符类:性格各异的字符们
      • 预定义字符类:常见角色的快捷方式
      • 重复限定符:贪婪的收集者
      • 贪婪vs非贪婪:胃口大小问题
      • 分组与捕获:给模式戴上名牌
    • 二、Python中的re模块:施展魔法的工具箱
      • 主要函数
      • 常用标志
    • 三、实际例子:魔法入门
      • 1. 验证邮箱地址
      • 2. 提取文本中的日期
      • 3. 提取并处理HTML标签
      • 4. 分割CSV,但忽略引号内的逗号
    • 四、正则表达式调试技巧:魔法训练
    • 五、正则表达式性能注意事项:魔力消耗控制
    • 总结:正则表达式修炼指南
    • 练习题:小试身手
      • 1.验证中国手机号码
      • 2. 从文本中提取所有URL链接
      • 3. 验证IPv4地址
      • 4. 提取Twitter风格的标签
      • 综合示例应用

什么是正则表达式?

想象一下,你是一位文本世界的探险家,需要在茫茫字符海洋中寻找特定的"宝藏"(模式)。正则表达式就是你的"寻宝地图"!

正则表达式(Regular Expression,简称regex)是一种强大的字符串搜索、匹配和操作的模式语言。它就像一个超级搜索工具,能帮你:

  • 🔍 查找特定模式的文本
  • ✂️ 替换文本中的特定内容
  • ✅ 验证文本是否符合特定格式(如邮箱、电话号码)
  • 🪓 分割文本为多个部分

在Python中使用正则表达式

Python通过re模块提供正则表达式支持:

import re

一、正则表达式基础语法:你的魔法咒语

基本匹配符

符号作用就像在说…
.匹配任意单个字符(除了换行符)“我不挑食,给我任何一个字符就行!”
^匹配字符串开头“我只关心句子的开头!”
$匹配字符串结尾“我只看结局!”
\转义特殊字符“别用魔法攻击我,这只是个普通字符!”

字符类:性格各异的字符们

符号作用就像在说…
[abc]匹配方括号内的任意一个字符“给我一个a或b或c就满足了”
[^abc]匹配除了方括号内的任意字符“除了abc,我都喜欢!”
[a-z]匹配a到z范围内的任意小写字母“给我一个小写字母就行”
[A-Z]匹配A到Z范围内的任意大写字母“我只收大写字母!”
[0-9]匹配任意数字“数字就行,不挑”

预定义字符类:常见角色的快捷方式

符号作用就像在说…
\d匹配任意数字,等同于[0-9]“来个数字吧!”
\D匹配任意非数字,等同于[^0-9]“数字以外的都行!”
\w匹配字母、数字或下划线,等同于[a-zA-Z0-9_]“给我一个’单词’字符!”
\W匹配非字母、数字、下划线的字符“不要’单词’字符!”
\s匹配任意空白字符(空格、制表符、换行符等)“我需要一点空间!”
\S匹配任意非空白字符“不要空白!”

重复限定符:贪婪的收集者

符号作用就像在说…
*匹配前面的模式零次或多次“有多少要多少,没有也行!”
+匹配前面的模式一次或多次“至少给我一个,多了也行!”
?匹配前面的模式零次或一次“有一个我就满足了,没有也无所谓”
{n}精确匹配前面的模式n次“我要正好n个,不多不少!”
{n,}匹配前面的模式至少n次“给我至少n个!”
{n,m}匹配前面的模式n到m次“给我n到m个之间,我很好说话的”

贪婪vs非贪婪:胃口大小问题

默认情况下,重复限定符是贪婪的,会尽可能多地匹配:

# 贪婪模式:尽可能多地匹配
re.search(r'a.*b', 'aabab').group()  # 'aabab'

加上?后,变成非贪婪模式,会尽可能少地匹配:

# 非贪婪模式:尽可能少地匹配
re.search(r'a.*?b', 'aabab').group()  # 'aab'

分组与捕获:给模式戴上名牌

符号作用就像在说…
(...)分组并捕获匹配的内容“这几个字符是一伙的,我要记住他们!”
(?:...)分组但不捕获匹配的内容“这几个字符是一伙的,但不用记住他们”
(?P<name>...)命名捕获组“这几个字符是一伙的,叫他们’name’”

二、Python中的re模块:施展魔法的工具箱

主要函数

函数作用记忆小窍门
re.search(pattern, string)在字符串中搜索第一个匹配项“找一找就好”
re.match(pattern, string)从字符串开头匹配模式“必须从头开始找”
re.findall(pattern, string)返回所有匹配项的列表“全都要找出来!”
re.finditer(pattern, string)返回所有匹配项的迭代器“一个一个慢慢找”
re.sub(pattern, repl, string)替换所有匹配项“找到就换掉”
re.split(pattern, string)按匹配项分割字符串“看到就切一刀”
re.compile(pattern)编译正则表达式模式“先准备好魔法卷轴”

常用标志

标志作用记忆小窍门
re.IGNORECASEre.I忽略大小写“A和a都一样”
re.MULTILINEre.M多行模式,使^$匹配每行的开始和结束“每行都很重要”
re.DOTALLre.S使.也能匹配换行符“点点无所不包”

三、实际例子:魔法入门

1. 验证邮箱地址

import redef is_valid_email(email):pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'return bool(re.match(pattern, email))# 测试一下
print(is_valid_email('user@example.com'))  # True
print(is_valid_email('invalid-email'))     # False

2. 提取文本中的日期

import retext = "今天是2023-05-15,明天是2023-05-16,后天是2023/05/17"# 找出所有日期
dates = re.findall(r'\d{4}[-/]\d{2}[-/]\d{2}', text)
print(dates)  # ['2023-05-15', '2023-05-16', '2023/05/17']

3. 提取并处理HTML标签

import rehtml = "<div>Hello <b>Python</b> and <i>Regex</i></div>"# 找出所有标签
tags = re.findall(r'<[^>]+>', html)
print(tags)  # ['<div>', '<b>', '</b>', '<i>', '</i>', '</div>']# 去除所有标签
clean_text = re.sub(r'<[^>]+>', '', html)
print(clean_text)  # 'Hello Python and Regex'

4. 分割CSV,但忽略引号内的逗号

# 这个例子展示了复杂模式的威力
import recsv_line = 'John,"Doe,Jr",New York,USA'# 错误的简单分割
print(csv_line.split(','))  # ['John', '"Doe', 'Jr"', 'New York', 'USA']# 使用正则表达式正确分割
pattern = r',(?=(?:[^"]*"[^"]*")*[^"]*$)'
print(re.split(pattern, csv_line))  # ['John', '"Doe,Jr"', 'New York', 'USA']

四、正则表达式调试技巧:魔法训练

  1. 小步前进:先测试简单的模式,然后逐渐添加复杂度
  2. 在线工具:使用regex101.com等在线工具进行可视化测试
  3. 分组使用:使用分组来隔离和测试正则表达式的各个部分
  4. 命名捕获组:给重要的捕获组命名,增强可读性

五、正则表达式性能注意事项:魔力消耗控制

  1. 避免过度回溯:复杂的嵌套重复限定符可能导致灾难性回溯
  2. 预编译模式:频繁使用的模式应该预编译
    phone_pattern = re.compile(r'\d{3}-\d{3}-\d{4}')
    # 重复使用phone_pattern.search()而不是re.search()
    
  3. 非捕获组:当不需要捕获结果时,使用非捕获组(?:...)提高性能
  4. 适当使用原子组:减少回溯的可能性

总结:正则表达式修炼指南

  • 正则表达式是强大的文本处理工具,但需要时间掌握
  • 从简单模式开始,逐步构建复杂模式
  • 多练习,多实验,才能掌握这门"魔法"
  • 记住:有时候,简单的字符串方法可能更适合简单的任务

“一开始,所有的正则表达式都像天书;熟练后,它们变成了你的得力助手。” – 正则表达式大师的传说

练习题:小试身手

  1. 编写一个正则表达式来验证中国手机号码(11位数字,以1开头)
  2. 从文本中提取所有的URL链接
  3. 验证一个字符串是否为有效的IPv4地址
  4. 从文本中提取所有的"#标签"(Twitter风格)

1.验证中国手机号码

中国手机号码规则:11位数字,以1开头。

import redef validate_chinese_phone(phone_number):"""验证中国手机号码是否有效参数:phone_number: 要验证的手机号码字符串返回:布尔值: 是否为有效的中国手机号码"""# 正则表达式解释:# ^1           - 以1开头# [0-9]{10}    - 后跟10位数字# $            - 结束匹配pattern = r'^1[0-9]{10}$'return bool(re.match(pattern, phone_number))# 测试示例
test_phones = ["13812345678",  # 有效"19912345678",  # 有效"12345678901",  # 有效 (只要求以1开头的11位数字)"138123456789", # 无效 (12位)"2381234567",   # 无效 (10位且不以1开头)"138abcd1234",  # 无效 (包含非数字字符)"01381234567",  # 无效 (12位且不以1开头)"138-1234-567"  # 无效 (包含连字符)
]for phone in test_phones:result = "有效" if validate_chinese_phone(phone) else "无效"print(f"手机号 {phone}{result}的中国手机号")

2. 从文本中提取所有URL链接

提取各种格式的URL链接,包括http、https、ftp等协议。

import redef extract_urls(text):"""从文本中提取所有URL链接参数:text: 要搜索的文本返回:列表: 包含所有找到的URL"""# 正则表达式解释:# (https?|ftp)://                - 匹配协议(http://, https://, ftp://)# [-a-zA-Z0-9@:%._\+~#=]{1,256}  - 匹配域名和路径中的有效字符# \.[a-zA-Z0-9()]{1,6}           - 匹配顶级域名(.com, .org等)# \b                             - 单词边界# ([-a-zA-Z0-9()@:%_\+.~#?&//=]*)- 匹配URL中的参数和路径pattern = r'(https?|ftp)://[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'# 简化版本,也可以使用这个更简单但覆盖面广的模式# pattern = r'https?://[^\s]+'return re.findall(pattern, text)# 测试示例
test_text = """
这是一个包含多个URL的文本示例:
访问 https://www.example.com 获取更多信息。
下载链接: http://files.example.org/document.pdf
FTP服务器: ftp://ftp.example.net/downloads/
无效链接: www.not-extracted.com (因为没有协议前缀)
嵌入在文本中的链接https://api.example.com/v1/data?id=123&format=json也会被提取。
"""urls = extract_urls(test_text)
print("提取的URL:")
for i, url in enumerate(urls, 1):print(f"{i}. {url[0]}{url[1]}")  # 合并捕获组

3. 验证IPv4地址

验证一个字符串是否为有效的IPv4地址(四个0-255之间的数字,用点分隔)。

import redef validate_ipv4(ip_address):"""验证一个字符串是否为有效的IPv4地址参数:ip_address: 要验证的IP地址字符串返回:布尔值: 是否为有效的IPv4地址"""# 正则表达式解释:# ^                         - 开始匹配# (25[0-5]|2[0-4][0-9]|     - 匹配250-255或200-249#  [01]?[0-9][0-9]?|        - 匹配0-199#  [0-9])                   - 匹配单个数字0-9# \.                        - 匹配点号(.)# 重复上述模式三次,最后一次不带点号# $                         - 结束匹配pattern = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$'return bool(re.match(pattern, ip_address))# 测试示例
test_ips = ["192.168.1.1",    # 有效"10.0.0.1",       # 有效"172.16.254.1",   # 有效"255.255.255.255",# 有效"0.0.0.0",        # 有效"256.0.0.1",      # 无效 (256超出范围)"192.168.1",      # 无效 (只有3段)"192.168.1.1.1",  # 无效 (有5段)"192.168.1.a",    # 无效 (包含非数字字符)"192.168.01.1"    # 有效 (前导零被允许)
]for ip in test_ips:result = "有效" if validate_ipv4(ip) else "无效"print(f"IP地址 {ip}{result}的IPv4地址")

4. 提取Twitter风格的标签

从文本中提取所有的"#标签"(Twitter风格)。

import redef extract_hashtags(text):"""从文本中提取所有的Twitter风格标签(#标签)参数:text: 要搜索的文本返回:列表: 包含所有找到的标签(不含#符号)"""# 正则表达式解释:# #                   - 匹配#符号# ([a-zA-Z0-9_\u4e00-\u9fa5]+) - 匹配标签内容:#   [a-zA-Z0-9_]     - 英文字母、数字和下划线#   \u4e00-\u9fa5    - 中文字符范围pattern = r'#([a-zA-Z0-9_\u4e00-\u9fa5]+)'return re.findall(pattern, text)# 测试示例
test_text = """
今天的天气真不错 #天气 #晴天
我正在学习Python #Python #编程 #学习
这是一个#复合标签 和一个 #带有标点符号的标签!
#中英文混合tag #123数字 #with_underscore
"""hashtags = extract_hashtags(test_text)
print("提取的标签:")
for i, tag in enumerate(hashtags, 1):print(f"{i}. {tag}")

综合示例应用

下面是一个综合应用,将上面的所有函数整合到一个文本分析工具中:

import reclass TextAnalyzer:"""文本分析工具,提供多种正则表达式功能"""@staticmethoddef validate_chinese_phone(phone_number):pattern = r'^1[0-9]{10}$'return bool(re.match(pattern, phone_number))@staticmethoddef extract_urls(text):pattern = r'(https?|ftp)://[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'matches = re.findall(pattern, text)return [f"{protocol}{path}" for protocol, path in matches]@staticmethoddef validate_ipv4(ip_address):pattern = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$'return bool(re.match(pattern, ip_address))@staticmethoddef extract_hashtags(text):pattern = r'#([a-zA-Z0-9_\u4e00-\u9fa5]+)'return re.findall(pattern, text)@staticmethoddef analyze_text(text):"""分析文本,提取所有可能的信息"""result = {"phones": [],"urls": [],"ips": [],"hashtags": []}# 提取手机号phone_pattern = r'1[0-9]{10}'phones = re.findall(phone_pattern, text)result["phones"] = [p for p in phones if TextAnalyzer.validate_chinese_phone(p)]# 提取URLresult["urls"] = TextAnalyzer.extract_urls(text)# 提取IP地址ip_pattern = r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'potential_ips = re.findall(ip_pattern, text)result["ips"] = [ip for ip in potential_ips if TextAnalyzer.validate_ipv4(ip)]# 提取标签result["hashtags"] = TextAnalyzer.extract_hashtags(text)return result# 测试综合分析
sample_text = """
联系我: 13812345678 或 19987654321
网站: https://www.example.com/path?query=123
服务器IP: 192.168.1.1 和 8.8.8.8 (但 999.999.999.999 不是有效IP)
话题: #Python #正则表达式 #数据分析
"""analyzer = TextAnalyzer()
analysis_result = analyzer.analyze_text(sample_text)print("文本分析结果:")
print(f"手机号: {analysis_result['phones']}")
print(f"URL链接: {analysis_result['urls']}")
print(f"IP地址: {analysis_result['ips']}")
print(f"话题标签: {analysis_result['hashtags']}")

这些正则表达式示例展示了如何使用Python处理各种文本模式匹配任务。您可以根据具体需求进一步调整这些模式,使它们更加精确或更适合您的用例。

记住:正则表达式就像厨艺,多练习才能精通。每解决一个文本处理问题,你就离正则表达式大师更近一步!

http://www.xdnf.cn/news/4754.html

相关文章:

  • 【C语言】--指针超详解(二)
  • 非对称加密:为什么RSA让“公开传密”成为可能
  • 计算机科技笔记: 容错计算机设计01 概述 教材书籍 课程安排 发展历史
  • Python连接云端服务器:基于Paramiko库的实践与问题剖析
  • LeetCode 3341.到达最后一个房间的最少时间 I:Dijkstra算法(类似深搜)-简短清晰的话描述
  • 9. 从《蜀道难》学CSS基础:三种选择器的实战解析
  • 密码学--RSA
  • 【AI提示词】费曼学习法导师
  • 缓存套餐-01.Spring Cache介绍和常用注解
  • LeetCode 3341到达最后一个房间的最少时间 I 题解
  • 基于大模型的计划性剖宫产全流程预测与方案优化研究报告
  • 跨浏览器自动化测试的智能生成方法
  • rom定制系列------红米note12 5G版miui14修改型号root版 原生安卓14批量线刷固件 原生安卓15等
  • STM32 ADC
  • 可撤销并查集,原理分析,题目练习
  • 数据结构(三)——栈和队列
  • 《P2880 [USACO07JAN] 平衡系列 G》
  • 【基础复习笔记】计算机视觉
  • 笔记本电脑实现网线内网 + Wi-Fi外网同时使用的配置方案
  • 运维打铁:服务器分类及PHP入门
  • 移植easylogger通过J-Linker的RTT输出日志/Ozone的RTT设置
  • 华为设备MSTP
  • 【IP101】图像压缩技术详解:从JPEG到小波压缩的完整指南
  • 机器人领域和心理学领域 恐怖谷 是什么
  • 如何为APP应用程序选择合适的服务器
  • C++ - 输入输出
  • Matlab 车辆四自由度垂向模型平稳性
  • Jupyter Notebook / Lab 疑难杂症记:从命令找不到到环境冲突与网络阻塞的排查实录
  • 手撕基于AMQP协议的简易消息队列-8(单元测试的编写)
  • linux mutex 互斥锁实现