正则表达式是处理文本数据的强大工具,Python通过re模块提供了完整的正则表达式功能。本文将详细介绍Python正则表达式的使用方法,包括基础语法、高级技巧和re模块API的详细解析。

一、正则表达式基础

1.1 什么是正则表达式

正则表达式(Regular Expression)是一种用于匹配字符串中字符组合的模式,可以用于搜索、替换和验证文本数据。

1.2 Python中的re模块

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

import re

二、正则表达式基本语法

2.1 普通字符

大多数字母和字符只会匹配它们自身:

pattern = r"hello"
text = "hello world"
match = re.search(pattern, text)
if match:print("找到匹配:", match.group())  # 输出: 找到匹配: hello

2.2 元字符

正则表达式中具有特殊含义的字符:

  • . 匹配任意单个字符(除了换行符)

  • ^ 匹配字符串的开头

  • $ 匹配字符串的结尾

  • * 匹配前面的子表达式零次或多次

  • + 匹配前面的子表达式一次或多次

  • ? 匹配前面的子表达式零次或一次

  • {m,n} 匹配前面的子表达式m到n次

  • [] 字符集,匹配其中任意一个字符

  • | 或操作,匹配左边或右边的表达式

  • () 分组,标记一个子表达式的开始和结束位置

2.3 字符类

  • \d 匹配任意数字,等价于[0-9]

  • \D 匹配任意非数字字符

  • \s 匹配任意空白字符(空格、制表符、换行符等)

  • \S 匹配任意非空白字符

  • \w 匹配任意字母数字字符,等价于[a-zA-Z0-9_]

  • \W 匹配任意非字母数字字符

三、re模块API详解

3.1 re.compile(pattern, flags=0)

编译正则表达式模式,返回一个正则表达式对象。

参数说明:

  • pattern: 要编译的正则表达式字符串

  • flags: 可选标志,用于修改正则表达式的匹配方式

常用flags:

  • re.IGNORECASE 或 re.I: 忽略大小写

  • re.MULTILINE 或 re.M: 多行模式,影响^和$

  • re.DOTALL 或 re.S: 使.匹配包括换行符在内的所有字符

示例:

# 编译一个正则表达式对象
pattern = re.compile(r'\d{3}-\d{3}-\d{4}', re.IGNORECASE)# 使用编译后的对象进行匹配
text = "我的电话号码是123-456-7890"
match = pattern.search(text)
if match:print("找到电话号码:", match.group())  # 输出: 找到电话号码: 123-456-7890

3.2 re.search(pattern, string, flags=0)

扫描整个字符串并返回第一个成功的匹配。

参数说明:

  • pattern: 要匹配的正则表达式

  • string: 要搜索的字符串

  • flags: 可选标志

示例:

text = "Python是一种流行的编程语言,Python简单易学"
match = re.search(r'Python', text)
if match:print("找到匹配:", match.group())  # 输出: 找到匹配: Pythonprint("匹配位置:", match.span())  # 输出: 匹配位置: (0, 6)

3.3 re.match(pattern, string, flags=0)

尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,就返回None。

与search的区别:

  • match只在字符串开头匹配

  • search在整个字符串中搜索第一个匹配

示例:

text1 = "Python很棒"
text2 = "学习Python很棒"print(re.match(r'Python', text1))  # 返回匹配对象
print(re.match(r'Python', text2))  # 返回None

3.4 re.findall(pattern, string, flags=0)

返回字符串中所有与模式匹配的非重叠匹配项,作为字符串列表。

示例:

text = "苹果10元,香蕉5元,橙子8元"
prices = re.findall(r'\d+元', text)
print(prices)  # 输出: ['10元', '5元', '8元']

3.5 re.finditer(pattern, string, flags=0)

返回一个迭代器,产生所有非重叠匹配的匹配对象。

与findall的区别:

  • findall返回字符串列表

  • finditer返回匹配对象迭代器

示例:

text = "Python 3.8, Python 3.9, Python 3.10"
matches = re.finditer(r'Python \d+\.\d+', text)
for match in matches:print(f"找到: {match.group()} 在位置 {match.span()}")
# 输出:
# 找到: Python 3.8 在位置 (0, 9)
# 找到: Python 3.9 在位置 (11, 20)
# 找到: Python 3.10 在位置 (22, 32)

3.6 re.sub(pattern, repl, string, count=0, flags=0)

替换字符串中的匹配项。

参数说明:

  • pattern: 正则表达式模式

  • repl: 替换的字符串或函数

  • string: 原始字符串

  • count: 最大替换次数,0表示替换所有

  • flags: 可选标志

示例:

text = "今天是2023-05-15,明天是2023-05-16"
# 替换日期格式
new_text = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\1年\2月\3日', text)
print(new_text)  # 输出: 今天是2023年05月15日,明天是2023年05月16日# 使用函数作为替换
def to_upper(match):return match.group().upper()text = "hello world"
new_text = re.sub(r'\w+', to_upper, text)
print(new_text)  # 输出: HELLO WORLD

3.7 re.split(pattern, string, maxsplit=0, flags=0)

按照能够匹配的子串将字符串分割后返回列表。

参数说明:

  • pattern: 分隔符正则表达式

  • string: 要分割的字符串

  • maxsplit: 最大分割次数,0表示不限制

  • flags: 可选标志

示例:

text = "苹果,香蕉,,橙子, 西瓜"
# 按逗号分割,忽略空格和空字符串
items = re.split(r'\s*,\s*', text.strip())
print(items)  # 输出: ['苹果', '香蕉', '', '橙子', '西瓜']# 使用多个分隔符
text = "苹果 香蕉,橙子;西瓜"
items = re.split(r'[ ,;]', text)
print(items)  # 输出: ['苹果', '香蕉', '橙子', '西瓜']

四、匹配对象的方法

当使用search()match()成功匹配后,会返回一个匹配对象,该对象有以下方法:

4.1 group([group1, ...])

返回匹配的一个或多个子组。

示例:

text = "John Doe, 30岁"
match = re.search(r'(\w+) (\w+), (\d+)岁', text)
if match:print("完整匹配:", match.group(0))  # 输出: 完整匹配: John Doe, 30岁print("名字:", match.group(1))     # 输出: 名字: Johnprint("姓氏:", match.group(2))     # 输出: 姓氏: Doeprint("年龄:", match.group(3))     # 输出: 年龄: 30print("所有组:", match.groups())   # 输出: 所有组: ('John', 'Doe', '30')

4.2 groups(default=None)

返回一个包含所有子组的元组。

4.3 groupdict(default=None)

返回一个包含所有命名子组的字典,键为子组名。

4.4 start([group]) 和 end([group])

返回匹配的子组的开始和结束位置。

4.5 span([group])

返回一个元组包含匹配的子组的 (开始, 结束) 位置。

五、高级正则表达式技巧

5.1 非贪婪匹配

默认情况下,*+是贪婪的,会匹配尽可能多的字符。添加?使其变为非贪婪:

text = "<h1>标题</h1><p>段落</p>"
# 贪婪匹配
greedy = re.search(r'<.*>', text)
print(greedy.group())  # 输出: <h1>标题</h1><p>段落</p># 非贪婪匹配
non_greedy = re.search(r'<.*?>', text)
print(non_greedy.group())  # 输出: <h1>

5.2 前向断言和后向断言

  • (?=...) 正向前视断言

  • (?!...) 负向前视断言

  • (?<=...) 正向后视断言

  • (?<!...) 负向后视断言

示例:

# 匹配后面跟着"元"的数字
text = "苹果10元,香蕉5元,橙子8个"
prices = re.findall(r'\d+(?=元)', text)
print(prices)  # 输出: ['10', '5']# 匹配前面是"价格:"的数字
text = "价格:100,数量:5"
numbers = re.findall(r'(?<=价格:)\d+', text)
print(numbers)  # 输出: ['100']

5.3 命名组

使用(?P<name>...)语法为组命名:

text = "2023-05-15"
match = re.search(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})', text)
if match:print(match.groupdict())  # 输出: {'year': '2023', 'month': '05', 'day': '15'}

5.4 条件匹配

使用(?(id/name)yes-pattern|no-pattern)

# 如果第一个组匹配"Mr",则匹配"Smith",否则匹配"Smithson"
text1 = "Mr Smith"
text2 = "Mrs Smithson"
pattern = r'(Mr)? (?(1)Smith|Smithson)'print(re.match(pattern, text1))  # 匹配
print(re.match(pattern, text2))  # 匹配

六、实际应用示例

6.1 验证电子邮件地址

def validate_email(email):pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'return re.match(pattern, email) is not Noneprint(validate_email("test@example.com"))  # True
print(validate_email("invalid.email@"))    # False

6.2 提取URL信息 

def extract_url_info(url):pattern = r'(https?)://([^/]+)(/.*)?'match = re.match(pattern, url)if match:return {'protocol': match.group(1),'domain': match.group(2),'path': match.group(3) or '/'}return Noneurl_info = extract_url_info("https://www.example.com/path/to/page")
print(url_info)
# 输出: {'protocol': 'https', 'domain': 'www.example.com', 'path': '/path/to/page'}

6.3 日志分析 

log_line = '127.0.0.1 - - [10/May/2023:15:32:45 +0800] "GET /index.html HTTP/1.1" 200 1234'pattern = r'^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) (\S+)" (\d+) (\d+)'
match = re.match(pattern, log_line)if match:log_data = {'ip': match.group(1),'time': match.group(2),'method': match.group(3),'path': match.group(4),'protocol': match.group(5),'status': int(match.group(6)),'size': int(match.group(7))}print(log_data)# 输出: {'ip': '127.0.0.1', 'time': '10/May/2023:15:32:45 +0800', # 'method': 'GET', 'path': '/index.html', 'protocol': 'HTTP/1.1',# 'status': 200, 'size': 1234}

七、性能优化建议

  1. 预编译正则表达式:对于重复使用的正则表达式,使用re.compile()预先编译。

  2. 使用非贪婪匹配:当可能时,使用非贪婪限定符*?+?等。

  3. 避免回溯灾难:复杂的正则表达式可能导致性能问题,尽量简化。

  4. 使用原子组(?>...)可以防止回溯。

  5. 合理使用字符类[abc](a|b|c)更高效。

八、常见问题与解决方案

8.1 匹配多行文本

使用re.MULTILINE标志:

text = """第一行
第二行
第三行"""
matches = re.findall(r'^第\w+', text, re.MULTILINE)
print(matches)  # 输出: ['第一行', '第二行', '第三行']

8.2 忽略大小写匹配

使用re.IGNORECASE标志:

text = "Python python PYTHON"
matches = re.findall(r'python', text, re.IGNORECASE)
print(matches)  # 输出: ['Python', 'python', 'PYTHON']

8.3 匹配Unicode字符

使用\u\x转义,或直接包含Unicode字符:

text = "中文Chinese にほんご"
matches = re.findall(r'[\u4e00-\u9fa5]+', text)  # 匹配中文字符
print(matches)  # 输出: ['中文']

九、总结

Python的正则表达式功能强大而灵活,re模块提供了丰富的API来处理各种文本匹配需求。掌握正则表达式可以大大提高文本处理的效率和能力。记住:

  1. 复杂的正则表达式可以先分解为多个简单的部分

  2. 使用re.VERBOSE标志可以使复杂的正则表达式更易读

  3. 测试正则表达式时可以使用在线工具如regex101.com

  4. 对于非常复杂的文本处理,可能需要结合其他方法(如解析器)

希望本博客能帮助你掌握Python正则表达式的使用!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87959.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87959.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/87959.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytest合并allure报告解决方案

背景 在执行自动化测试的过程中&#xff0c;为了实现自动化的高通过率&#xff0c;可能会反复的重试&#xff0c;直至大多数甚至全部用例执行通过&#xff0c;以此来需要人为分析的用例量&#xff0c;减少人力投入&#xff0c;提高执行效率&#xff1b; 在用例少或者资源消耗小…

Pr插件图文安装教程

Pr插件图文安装教程 Adobe Premiere Pro&#xff0c;简称Pr&#xff0c;是由Adobe公司开发的一款视频编辑软件。Adobe Premiere有较好的兼容性&#xff0c;且可以与Adobe公司推出的其他软件相互协作。这款软件广泛应用于广告制作和电视节目制作中&#xff0c;是视频编辑爱好者…

[netty5: HttpObjectEncoder HttpObjectDecoder]-源码解析

在阅读该篇文章之前&#xff0c;推荐先阅读以下内容&#xff1a; [netty5: HttpObject]-源码解析[netty5: MessageToMessageCodec & MessageToMessageEncoder & MessageToMessageDecoder]-源码分析[netty5: ByteToMessageCodec & MessageToByteEncoder & Byte…

uniapp的navigator跳转功能

接下来&#xff0c;我将围绕一个常见的电商小程序来构建一系列连贯的使用场景。在这个过程中&#xff0c;我们将把 <navigator> 组件的所有关键属性和方法都串联起来&#xff0c;并详细解释它们在每个环节所扮演的角色和作用。 核心场景&#xff1a;构建一个电商小程序的…

v-for的用法及案例

目录 一.v-for的用法 1.举例1 2.举例2 二.购物车案例 1.代码 2.存在的问题&#xff1a;复选框错位 3.解决方案&#xff1a; 赋值给key属性一个唯一的值 一.v-for的用法 1.举例1 <template><view><view v-for"(item,index) in 10" :key"…

BigQuery对象引用(ObjectRef)全面指南:一站式整合结构化与非结构化多模态数据分析

引言 企业需要同时管理有组织表格中的结构化数据&#xff0c;以及日益增长的非结构化数据&#xff08;如图片、音频和文档&#xff09;。传统上&#xff0c;联合分析这些多样化数据类型非常复杂&#xff0c;通常需要使用不同的工具。非结构化媒体通常需要导出到专门的服务进行…

【开源品鉴】FRP源码阅读

frp 是一款高性能的反向代理应用&#xff0c;专注于内网穿透&#xff0c;支持多种协议和 P2P 通信功能&#xff0c;目前在 GitHub 上已有 80k 的 star。本文将深入探讨其源码&#xff0c;揭示其背后的实现原理。1. 前言 frp 是一款高性能的反向代理应用&#xff0c;专注于内网…

day048-系统负载高排查流程与前后端分离项目

文章目录 0. 老男孩思想1. 系统负载高排查流程1.1 进程/线程相关命令1.1.1 jps1.1.2 jstack1.1.3 jmap1.1.4 top -Hp pid 1.2 排查流程图 2. 前后端分离项目2.1 项目说明2.2 负载均衡2.3 数据库配置2.3.1 安装数据库服务2.3.2 配置数据库环境 2.4 后端配置2.5 四层负载均衡配置…

Spring Boot 牵手EasyExcel:解锁高效数据处理姿势

引言 在日常的 Java 开发中&#xff0c;处理 Excel 文件是一个极为常见的需求。无论是数据的导入导出&#xff0c;还是报表的生成&#xff0c;Excel 都扮演着重要的角色。例如&#xff0c;在企业的财务管理系统中&#xff0c;需要将每月的财务数据导出为 Excel 报表&#xff0…

【ARM AMBA AXI 入门 21 -- AXI partial 访问和 narrow 访问的区别】

文章目录 Overview一、定义区别二、AXI 信号层面对比三、举例说明示例一:Partial Access示例二:Narrow Access四、硬件/系统处理角度五、AXI 总线接口信号举例对比Partial Write 事务:Narrow Write 事务(32-bit Master on 64-bit Bus):六、总结对比表七,软件判断判断 Pa…

使用Ideal创建一个spring boot的helloWorld项目

说明&#xff1a;本篇将介绍如何使用Ideal2024.2.1去创建一个spring boot的helloWorld项目&#xff0c;本篇将包含创建的详细步骤以及spring boot项目的目录结构说明&#xff0c;创建过程中的选项说明等。详细步骤如下&#xff1a;第一步&#xff1a;点击文件——新建——项目&…

国内Ubuntu访问不了github等外网

各位小伙伴们&#xff0c;大家好呀。 大家是不是经常遇到访问不了外网的情况呀。 在Ubuntu中可以这样做。 访问这个网站网站测速-Ping检测-Trace查询-Dig查询-路由跟踪查询-tools.ipip.net&#xff0c; 对于github.com&#xff0c;在这个网站输入github.com&#xff0c;会返…

PDF转换工具,即开即用

在办公室里&#xff0c;这句话被反复验证。每天面对成堆的Word和Excel文件&#xff0c;将它们转换成PDF格式是常有的事。可之前用过的工具&#xff0c;不是一次只能转一个&#xff0c;就是操作繁琐得让人头疼。记得有次赶项目&#xff0c;需要把二十多个文档转成PDF&#xff0c…

2. 你可以说一下 http 版本的发展过程吗

你可以说一下 http 版本的发展过程吗 总结&#xff1a;0.9&#xff1a;只能发送 get&#xff0c;无状态。1.0&#xff1a;新增 post&#xff0c;请求头&#xff0c;状态码&#xff0c;cookie。1.1&#xff1a;新增 put/delete/options/patch&#xff0c;keep-alive&#xff0c…

04-Linux驱动模块的自动加载

概述 上一节&#xff0c;我们讲述了Linux驱动开发的基本的模块代码编写和手动执行模块加载的操作&#xff0c; 这一节&#xff0c;我们讲述嵌入式设备上使用Sysvint引导方式下如何开机自动加载模块的步骤。感兴趣的同学看下使用systemd引导方式的开启自动加载模块的步骤 操作…

【牛客算法】游游的整数切割

文章目录 一、题目介绍1.1 题目链接1.2 题目描述1.3 输入描述1.4 输出描述1.5 示例二、解题思路2.1 核心算法设计2.2 性能优化关键2.3 算法流程图三、解法实现3.1 解法一:基础遍历法3.1.1 初级版本分析3.2 解法二:奇偶预统计法(推荐)3.2.1 优化版本分析四、总结与拓展4.1 关…

笔记本电脑忽亮忽暗问题

关于笔记本电脑忽亮忽暗的问题这个问题困扰了我大半年&#xff0c;最后忽然找到解决方法了---主要的话有三种可能性1.关闭显示器自动调亮的功能2.关闭节能模式自动调亮功能3.调整显卡的功率&#xff0c;关闭自动调亮功能一开始一直都是尝试的第一种方法&#xff0c;没解决。。。…

Qt的顶部工具栏在多个界面使用

Qt的工具栏在多个界面使用1、前言2、创建一个工具栏类2.1 新建一个工具栏类3、提升工具栏类3.1登录界面添加工具栏3.2 创建工具栏对象4、总结1、前言 今天遇到了个问题&#xff0c;顶部的工具栏&#xff0c;像软键盘&#xff0c;时间显示和退出按钮那些&#xff0c;想在多个界…

C#和SQL Server连接常用通讯方式

C#和SQL Server连接通讯 在 C# 中与 SQL Server 建立数据库连接&#xff0c;主要通过 ADO.NET 技术实现。以下是几种常见的连接方式及相关实践&#xff1a; ADO.NET 全面指南&#xff1a;C# 数据库访问核心技术 ADO.NET 是 .NET Framework 中用于数据访问的核心组件&#xf…

安卓10.0系统修改定制化____实现自动开启 USB 调试​的步骤解析 列举常用的几种修改方法

对于安卓开发者、测试人员,甚至是喜欢折腾手机的数码爱好者来说,USB 调试是一个非常重要的功能。它能让手机与电脑相连,实现应用安装、系统调试、数据传输等操作。但每次连接手机都要手动去设置里开启 USB 调试,实在麻烦。其实,通过修改安卓 10.0 的 ROM,就能让手机自动开…