正则表达式梳理(基于python)

正则表达式(regular expression)是一种针对字符串匹配查找所定义的规则模式,独立于语言,但不同语言在实现上也会存在一些细微差别,下面基于python对常用的相关内容进行梳理。

文章目录

  • 一、通用常识
    • 1.通配符
      • ps.反义
    • 2.量词
      • ps.非贪婪匹配
    • 3.位置限定符
    • 4.其他特殊符号
  • 二、python实现
    • 1.常用函数
      • 1)search
      • 2)match
      • 3)findall
    • 2.特殊用法
      • 1) `(?:...) `非捕获组
      • 2)`(?=...)`正向先行断言
      • 3)`(?!...)`负向先行断言
      • 4)`(?<=...)`正向后行断言
      • 5)`(?<=...)`负向后行断言
      • ps1.理解 先行/后行 & 正向/负向
      • ps2.后行断言时,限定字符的长度必须固定

一、通用常识

1.通配符

.:匹配任意字符。(换行符除外)
\w:匹配字母、数字、下划线。(也可以写为[a-zA-Z0-9_]
\d:匹配阿拉伯数字([0-9])。
\s:匹配空白字符。(空格、制表符、换行符等)
[ ]:匹配列表中任意字符。(所有特殊字符在列表中都会按照字面量对待,不需要特殊转义)

ps.反义

\W:匹配非字母、数字、下划线外的字符。
\D:匹配非阿拉伯数字。
\S:匹配非空白字符。
[^ ]:不匹配列表中任意字符。

2.量词

?:0次或1次。
+:1次或多次。
*:0次或多次。
{m}:精确匹配m次。
{m,n}:匹配m~n次。
{m,}:至少匹配m次。

ps.非贪婪匹配

贪婪匹配:满足正则的情况下尽可能多的匹配。
非贪婪匹配:满足正则的情况下尽可能少的匹配。

默认正则中都是贪婪匹配,需要非贪婪匹配时需要在量词后面加个?

3.位置限定符

^:限制起始字符。
$:限制结尾字符。

4.其他特殊符号

|:逻辑或,匹配逻辑或中的任意一个。
\:转义字符,通常对\本身进行转义。

二、python实现

python中实现正则的标准库是re,下面主要介绍该模块中常用的一些方法及作用。

1.常用函数

1)search

匹配目标字符串第一个出现的符合正则的子串,匹配成功返回Match对象,匹配失败返回None

返回的Match对象可通过group方法获取指定捕获组()的内容,无论正则中有没有指定捕获组,默认的捕获组都是0,即整个符合正则的子串。

当在正则中显式指定捕获组时,捕获组索引号按照在正则中从左到右的顺序自1开始递增。

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import rematch = re.search(r'(\d+路)(\d+号)(\d+楼)', '北京市昌平区1路2号3楼')
print(match.group())
print(match.group(1))
print(match.group(2))
print(match.group(3))# 1路2号3楼
# 1路
# 2号
# 3楼

当出现捕获组嵌套的情况时,同样是按照在正则中从左往右出现的顺序解析对应,只不过是递归解析,类似于树的先序遍历。

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import rematch = re.search(r'((\d+路)(\d+号))(\d+楼)', '北京市昌平区1路2号3楼')
print(match.group())
print(match.group(1))
print(match.group(2))
print(match.group(3))
print(match.group(4))# 1路2号3楼
# 1路2号
# 1路
# 2号
# 3楼

2)match

match方法和search用法及返回的对象都一致,唯一的区别是search的目标子串可以出现在字符串中的任何位置,而match是从开头开始匹配,目标子串必须在字符串开头出现。

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import rematch = re.match(r'((\d+路)(\d+号))(\d+楼)', '北京市昌平区1路2号3楼')
if match:print(match.group())print(match.group(1))print(match.group(2))print(match.group(3))print(match.group(4))
else:print('None')# None

在正则前面加个.*适配就可以成功匹配了:

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import rematch = re.match(r'.*((\d+路)(\d+号))(\d+楼)', '北京市昌平区1路2号3楼')
if match:print(match.group())print(match.group(1))print(match.group(2))print(match.group(3))print(match.group(4))
else:print('None')# 北京市昌平区1路2号3楼
# 1路2号
# 1路
# 2号
# 3楼

3)findall

顾名思义,找出字符串中所有匹配正则的子串。无论有无匹配返回的结果都是一个列表。

当正则中无捕获组或者仅有一个捕获组时,返回的是包含单个元素的列表,每个元素都是一个匹配项。

无捕获组返回的是匹配整个正则的子串,1个捕获组返回的是匹配捕获组的子串。

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import reans1 = re.findall(r'\d+路\d+号\d+楼', '北京市昌平区1路2号3楼')
print(ans1)ans2 = re.findall(r'(\d+路)\d+号\d+楼', '北京市昌平区1路2号3楼')
print(ans2)# ['1路2号3楼']
# ['1路']

当正则中包含多个捕获组时,返回包含元组的列表,每个元组是一个正则匹配项,元组中的元素对应了每个匹配项中捕获组的匹配内容,无匹配时用空字符串''代替。

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import reans1 = re.findall(r'((\d+路)(\d+号))(\d+楼)', '北京市昌平区1路2号3楼')
print(ans1)ans2 = re.findall(r'((\d+路)?(\d+号))(\d+楼)', '北京市昌平区2号3楼')
print(ans2)# [('1路2号', '1路', '2号', '3楼')]
# [('2号', '', '2号', '3楼')]

ps:特别注意正则中包含逻辑或|时,无论匹配的是哪个逻辑分支,其余的逻辑分支中的捕获组都会在元组中用空字符串''表示。

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import reans = re.findall(r'B(\d+)层([A-Z]+)区|地下([一二三四五六七八九]+)层([A-Z]+)区','停车场B2层C区;停车场地下一层B区')
print(ans)# [('2', 'C', '', ''), ('', '', '一', 'B')]

2.特殊用法

1) (?:...) 非捕获组

仅匹配,不捕获。通常用于目标需要提取的捕获组前的限制规则比较复杂,需要用到()的场景。

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import reans = re.findall(r'(?:B|地下)[1-9一二三四五六七八九]+层([A-Z]+区)','停车场B2层C区;停车场地下一层B区')
print(ans)# ['C区', 'B区']

2)(?=...)正向先行断言

这里的正向先行的意思是,右侧必须出现可以匹配括号中...的字符,这种方式在实际匹配过程中只会预先查找,不会实际消耗字符串。

比如从下面的日期中提取月份:

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import rematch = re.search(r'\d+(?=月)', '今天是2025年3月5日')
if match:print(match)# <re.Match object; span=(8, 9), match='3'>

3)(?!...)负向先行断言

负向先行:右边不能出现匹配括号中...的字符。

提取日期号,不提取年和月份:

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import rematch = re.search(r'\d+(?![年月0-9])', '今天是2025年3月5日')
if match:print(match)# <re.Match object; span=(10, 11), match='5'>

4)(?<=...)正向后行断言

正向后行:左边必须出现匹配括号中...的字符。

只提取折扣价:

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import rematch = re.search(r'(?<=折扣价)\d+', '原价100;折扣价80;实付价70')
if match:print(match)# <re.Match object; span=(9, 11), match='80'>

5)(?<=...)负向后行断言

负向后行:左边不能出现匹配括号中...的字符。

只提取原价:

#!/usr/bin/env python3
# -*-coding:utf-8 -*-import rematch = re.search(r'(?<!(折扣价|实付价))\d+', '原价100;折扣价80;实付价70')
if match:print(match)# <re.Match object; span=(2, 5), match='100'>

ps1.理解 先行/后行 & 正向/负向

​先行断言​:检查匹配位置的 ​右侧​ 是否符合条件。
​后行断言:检查匹配位置的 ​左侧​ 是否符合条件。

个人觉得,先行/后行 可以理解成目标匹配子串相对于限定字符的 左边/右边。

​正向​:匹配 ​存在​ 某个条件。
​负向​:匹配 ​不存在​ 某个条件。

ps2.后行断言时,限定字符的长度必须固定

在这里插入图片描述
内置文档中提示先行断言限定字符长度无特殊限制,后行断言限定字符长度必须固定。

原因是正则引擎的默认匹配方向是从左到右,当遇到先行断言时,引擎会临时向右扫描,检查后续字符是否符合断言条件。由于匹配方向与引擎的默认方向一致,变长模式不会导致回溯问题。

而后行断言时正则引擎需要反向检查左侧的字符,而反向匹配需要明确的起始位置。如果后行断言是变长模式(如.*a+),引擎无法确定从哪个位置开始检查,导致性能下降或无法实现。

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

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

相关文章

Java多线程与高并发专题——为什么 Map 桶中超过 8 个才转为红黑树?

引入 JDK 1.8 的 HashMap 和 ConcurrentHashMap 都有这样一个特点&#xff1a;最开始的 Map 是空的&#xff0c;因为里面没有任何元素&#xff0c;往里放元素时会计算 hash 值&#xff0c;计算之后&#xff0c;第 1 个 value 会首先占用一个桶&#xff08;也称为槽点&#xff…

Llama-Factory框架下的Meta-Llama-3-8B-Instruct模型微调

目录 引言 Llama - Factory 训练框架简介&#xff1a; Meta - Llama - 3 - 8B - Instruct 模型概述&#xff1a; Lora 方法原理及优势&#xff1a; 原理 优势 环境准备: 部署环境测试&#xff1a; 数据准备&#xff1a; 模型准备&#xff1a; 模型配置与训练&#xff1…

介绍一个能支持高带宽的EDID编辑软件

软件名称叫980 Manager 4.24.16&#xff0c;安装后的图标如下。   软件可以去此地址下载https://download.csdn.net/download/cjie221/90459603&#xff0c;下载后需解压&#xff0c;运行.msi文件安装。   安装后&#xff0c;打开软件&#xff0c;首先会弹出这个界面&…

2025年Cursor最新安装使用教程

Cursor安装教程 一、Cursor下载二、Cursor安装三、Cursor编辑器快捷键(1) 基础编辑快捷键(2) 导航快捷键(3) 其他常用快捷键 一、Cursor下载 Cursor官方网站&#xff08;https://www.cursor.com/ &#xff09; 根据自己电脑操作系统选择对应安装包 二、Cursor安装 下载完成后…

[内网安全] Windows 本地认证 — NTLM 哈希和 LM 哈希

关注这个专栏的其他相关笔记&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01&#xff1a;SAM 文件 & Windows 本地认证流程 0x0101&#xff1a;SAM 文件简介 Windows 本地账户的登录密码是存储在系统本地的 SAM 文件中的&#xff0c;在登录 Windows 的时候&am…

pt-archiver删除数据库的数据表/各种报错类型

这篇帖子是前面文的一部分延申 mysqlimport导入一亿数据的csv文件/一行命令删除表-CSDN博客 如需转载&#xff0c;标记出处 目录 pt-archiver命令格式 如果执行后出现下面报错 1&#xff09;Cannot find an ascendable index in table at /usr/bin/pt-archiver line 3233. …

开发环境搭建-06.后端环境搭建-前后端联调-Nginx反向代理和负载均衡概念

一.前后端联调 我们首先来思考一个问题 前端的请求地址是&#xff1a;http://localhost/api/employee/login 后端的接口地址是&#xff1a;http://localhost:8080/admin/employee/login 明明请求地址和接口地址不同&#xff0c;那么前端是如何请求到后端接口所响应回来的数…

自学Linux系统软件编程第八天

并发服务器&#xff1a; 服务器在同一时刻可以响应多个客户端的请求。 UDP&#xff1a;无连接 单循环服务器&#xff1a;服务器同一时刻只能响应一个客户端的请求。 TCP&#xff1a;有连接 构建TCP并发服务器&#xff1a; 让TCP服务端具备同时响应多个客户端的能力。 方法…

FusionInsight MRS云原生数据湖

FusionInsight MRS云原生数据湖 1、FusionInsight MRS概述2、FusionInsight MRS解决方案3、FusionInsight MRS优势4、FusionInsight MRS功能 1、FusionInsight MRS概述 1.1、数据湖概述 数据湖是一个集中式存储库&#xff0c;允许以任意规模存储所有结构化和非结构化数据。可以…

.NET 10首个预览版发布:重大改进与新特性概览!

前言 .NET 团队于2025年2月25日发布博文&#xff0c;宣布推出 .NET 10 首个预览版更新&#xff0c;重点改进.NET Runtime、SDK、Libraries 、C#、ASP.NET Core、Blazor 和.NET MAUI 等。 .NET 10介绍 .NET 10 是 .NET 9 的后继版本&#xff0c;将作为长期支持维护 &#xff…

HTTP 黑科技

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

C++20 模块:告别头文件,迎接现代化的模块系统

文章目录 引言一、C20模块简介1.1 传统头文件的局限性1.2 模块的出现 二、模块的基本概念2.1 模块声明2.2 模块接口单元2.3 模块实现单元 三、模块的优势3.1 编译时间大幅减少3.2 更好的依赖管理3.3 命名空间隔离 四、如何使用C20模块4.1 编译器支持4.2 示例项目4.3 编译和运行…

计算光学成像与光学计算概论

计算光学成像所涉及研究的内容非常广泛&#xff0c;虽然计算光学成像的研究内容是发散的&#xff0c;但目的都是一致的&#xff1a;如何让相机记录到客观实物更丰富的信息&#xff0c;延伸并扩展人眼的视觉感知。总的来说&#xff0c;计算光学成像现阶段已经取得了很多令人振奋…

安铂克科技 APPH 系列相位噪声分析仪:高性能测量的卓越之选

在当今的电子测量领域&#xff0c;对于信号源及各类设备的精确评估至关重要。安铂克科技的 APPH 系列相位噪声分析仪&#xff08;亦称作相噪仪、相位噪声测量仪、信号源分析仪&#xff09;&#xff0c;凭借其超凡的性能与全面的功能&#xff0c;成为众多工程师与科研人员的理想…

算法探秘:盛最多水的容器问题

目录 一、问题引入 二、示例剖析 三、暴力解法与困境 四、双指针法&#xff1a;优雅的解决方案 五、总结 一、问题引入 在算法的奇妙世界里&#xff0c;常常会遇到各种有趣又富有挑战性的问题&#xff0c;“盛最多水的容器”就是其中之一。想象一下&#xff0c;有一系…

QTday4

1:是进度条通过线程自己动起来 mythread.h #ifndef MYTHREAD_H #define MYTHREAD_H #include <QThread>class mythread : public QThread {Q_OBJECT public:mythread(QObject* parent nullptr); protected:virtual void run() override; private: signals:virtual voi…

PPT小黑第26套

对应大猫28 层次级别是错的&#xff0c;看着是十页&#xff0c;导入ppt之后四十多页 选中所有 红色蓝色黑色 文本选择标题&#xff1a;选择 -格式相似文本&#xff08;检查有没有漏选 漏选的话 按住ctrl 点下一个&#xff09; 要求新建幻灯片中不包含原素材中的任何格式&…

transformer架构解析{掩码,(自)注意力机制,多头(自)注意力机制}(含代码)-3

目录 前言 掩码张量 什么是掩码张量 掩码张量的作用 生成掩码张量实现 注意力机制 学习目标 注意力计算规则 注意力和自注意力 注意力机制 注意力机制计算规则的代码实现 多头注意力机制 学习目标 什么是多头注意力机制 多头注意力计算机制的作用 多头注意力机…

Spring编写单元测试的工具介绍:JUnit、Mockito、AssertJ

背景&#xff1a; 在Spring应用程序中&#xff0c;想要通过代码走查做好测试左移&#xff0c;单元测试是确保代码质量和功能正确性的关键。除了我们常用的TestNG外&#xff0c;本次介绍一下其他常见的单元测试工具: JUnit、Mockito、AssertJ&#xff0c;来提高我们做白盒测试的…

Kubermetes 部署mysql pod

步骤 1: 创建 PersistentVolume 和 PersistentVolumeClaim 首先为 MySQL 创建一个 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC) 来确保数据的持久性。 mysql-pv.yaml&#xff1a; apiVersion: v1 kind: PersistentVolume metadata:name: mysql-pv-volume spec:cap…