用人话讲计算机:Python篇!(十二)正则运算+re模块

news2024/12/12 14:00:53

目录

一、正则表达式

(1)什么是正则表达式

(2)它的结构及使用

示例:

1.字符 . (←这里有个小点哦)

2.字符 | 

3.字符 [ ] 

4.字符^

5.字符\d

(3)补充:表示数量

示例:

1.字符+

2.字符*

3.字符?

4.字符{n}

二、贪婪模式与非贪婪模式

(1)贪婪模式

(2)非贪婪模式

三、捕获组

四、re模块

(1)re库函数一览

(2)具体用法示例

1.re.findall(pattern,string,flags)

2.re.compile(pattern,[flags])

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

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

5.group 和 groups 函数

6.re.sub(pattern,replace,string,count=0,flags=0)

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


本节内容较长,有一定难度,还请耐心观看~~~

一、正则表达式

(1)什么是正则表达式

标准解释:正则表达式,又称规则表达式,它是一种文本模式,同时也是计算机科学的一个概 念,其中包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符 ")。

正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符 串,通常被用来检索、替换那些符合某个模式(规则)的文本。

简单来说,它就像一种“搜索语言”,它允许你通过特定的符号搜索你想要的文本

比如,你面前有一大堆文本文字,这时你就可以通过代码搜索找出你想要的有价值的文本

(2)它的结构及使用

正则表达式由两部分构成:一个是普通字符,一个是特殊字符。

所谓普通字符,就是a,b,c……z和A,B,C……Z这些英文字母、数字0到9、标点符号。

所谓特殊字符,又叫元字符,它包括:

看不懂,别急,直接后面看示例

字符作用
.匹配除\n 之外的任何单个字符。
|匹配两侧任意表达式
[ ]匹配里面的字符
^匹配以^之后字符开头的字符串
[^][^abc]表示非a或非b或 非c的单个字符
\d匹配一个数字字符,等价于[0-9]
\D匹配一个非数字字符,等价于[^0-9]
\s匹配任何空白字符,包括空格、制表符、换页符等等。
\S匹配任何非空白字符。等价于[^\f\n\r\t\v]
\w匹配任何单词字符,包括下划线。等价于“[A-Z和a-z和0-9_]”
\W匹配任何非单词字符。等价于“[^A-Za-z0-9_]”
\f匹配一个换页符
\n匹配一个换行符
\r匹配一个回车符

示例:

前言:正则表达式要用到re模块哦~~~

1.字符 . (←这里有个小点哦)

它的作用是,匹配除\n 之外的任何个字符。

这里用到了re模块的findall(a,b)函数 ,作用是 在b中搜索字符串a,然后以列表类型返回符合的字符串

例如:

import re
a=re.findall('张.',"张三,李四,王五,张六七")
print(a)

我们可以看到,需要匹配的字符串是 张. 翻译过来就是,匹配 张+张后面一个单字符。

所以,系统输出:

['张三', '张六']

当然你要是想匹配张和后面俩字符,就可以改成 张..  (←俩点)

就变成:

import re
a=re.findall('张..',"张三,李四,王五,张六七")
print(a)

系统输出:

['张三,', '张六七'] 

2.字符 | 

它的作用是,匹配两侧任意表达式,如果不存在,则不返回

比如:

import re
a=re.findall('cat|dog',"i have a cat and a dog")
print(a)

系统输出:

['cat', 'dog']

3.字符 [ ] 

它的作用是,匹配里面的字符

比如:

import re
a=re.findall('[ab]',"abcd齐齐")
print(a)

系统输出:

['a', 'b']

当然如果 [ ] 里有\n之类的话,为防止将 \ 被误解为转义符,最好是前面加个r,如:r‘[ab]’

4.字符^

他的作用是,匹配以^之后字符开头的字符串

如下面代码:^hello就是匹配以hello开头的字符串 

import re
a = re.findall('^hello', "hello world")
print(a)

系统输出:

['hello'] 

5.字符\d

它的作用是,匹配一个数字字符,等价于[0-9]

import re
a = re.findall(r'\d',"我的电话号码是110")
print(a)

输出:

['1', '1', '0']

注意,这里要用上了 r  防止 \  被误解哦~~

相信通过这5个例子,你应该初步掌握了,那么再回过头看那个表格是不是清楚多了

(3)补充:表示数量

当然了,正则表达式不仅只有上面那些。

它的特殊符还包括以下这些:

(还是一样,看不懂直接看示例)

字符作用
+匹配前面的子表达式一次或多次。
*匹配前面的子表达式零次或多次。
匹配前面的子表达式零次或一次。
{n}n是一个非负整数,匹配确定的n次。
{n,}n是一个非负整数,至少匹配n次。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹 配m次。
{,n}n是一个非负整数,至多匹配n次。

示例:

1.字符+

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

比如下面代码,a+,就相当于将开头是a的全部找出来

import re
print(re.findall('a+',"abcadefaaghaaa"))

系统输出:

['a', 'a', 'aa', 'aaa']

当然,上面可能说的不太准确,准确的来说,是将一个以a为开头,一个或多个a为结尾的找出来,我们可以看下面这个例子,ab+来理解一下:

import re
print(re.findall('ab+',"abcadefabaghabbcaba"))

系统输出:

['ab', 'ab', 'abb', 'ab']

我们可以看到它将一个以a为开头,一个或多个b为结尾的字符找了出来,简单来说,

就是除了最后面的字符b可以是一个或者很多个,但你前面的a必须是一个。

我们再来看一个例子理解一下,如abc+

import re
print(re.findall('abc+',"abcadeabbcababcc"))

系统输出:

['abc', 'abcc']

这里就是将一个以ab为开头,一个或多个c为结尾的字符找出来。

当然,标准的解释并不是这样,这只是对匹配一次或多次人话解释版本。

2.字符*

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

如果你能理解字符+,那么字符*也很好理解,比如下面代码:

import re
print(re.findall('ha*', "wo-hahaahh"))

系统输出:

['ha', 'haa', 'h', 'h']

我们用人话理解匹配零次或多次,就是将一个以h为开头,零个或多个a为结尾的找出来

3.字符?

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

如代码:

import re
print(re.findall('ha?',"wo-hahaahh"))

系统输出:

['ha', 'ha', 'h', 'h']

这里用人话理解匹配零次或一次,就是将一个以h为开头,零个或一个a为结尾的找出来

4.字符{n}

匹配确定的n次

我们经过理解,所谓的匹配几次就是,将一个以甲为开头,以几个乙为结尾的找出来

那么这里,也是一样的。比如我们匹配三次ab,那就是一个a开头,三个b为结尾的:

import re
print(re.findall('ab{3}',"ababbabbbabbbb"))

输出:

['abbb', 'abbb']

如果这个你能理解,相信{n,m}什么的,看看上面的表格的功能介绍,你也能理解了吧。

二、贪婪模式与非贪婪模式

所谓贪不贪婪啊,其实就是你要匹配多少个。

你想匹配的多了,那就是贪婪模式,想匹配少点,那就叫非贪婪模式喽~~

(1)贪婪模式

我们经过上面的学习,是不是已经发现计算机每次都默认匹配多次了,比如字符+和*之类。

对,所以啊,出现诸如:“{m,n}”、“{m,}”、“?”、“*”和“+”之类的,那都默认是贪婪模式。

我们在上面已经学习清楚了,就不再多赘述贪婪模式。

现在来将一个概念:回溯

标准解释:在匹配过程中,如果后面的部分无法匹配成功,贪婪模式会进行回溯, 即让出已经匹配成功的一部分字符,以便使整个表达式能够匹配成功。

有没有感觉很熟悉,这不就是我一直说的人话解释吗:将一个以甲为开头,以几个乙为结尾的找出来。

简单来说,就是我去匹配ab,在一串字符abbb中,字符+匹配,第一次匹配,我匹配到了ab,然后我想接着匹配,我想找a,但是没有啊,所以我就回溯,就是不要第一个已经匹配成功的字符a了,我就找b就行了,所以最后输出abbb

以上便是贪婪模式。

当然,如果关于回溯你没有太懂,没关系,这不重要,你只要记住我的人话版,一样能写代码。

(2)非贪婪模式

非贪婪模式与贪婪模式相反,它会在匹配成功的前提下,尽可能少地匹配字 符。

还是比如,我在一串字符abbb中用字符+去匹配ab,在非贪婪模式下,我只会得到ab

这还是很好理解的。

非贪婪模式的表示:在字符后面加一个?

比如ab+?、ab*?、ab??、ab{3,5}?

我们来看一个代码,加深理解:

import re
print(re.findall('ab*?',"abbbbbbbbcd"))
print(re.findall('ab+?',"abbbbbbbbcd"))
print(re.findall('ab??',"abbbbbbbbcd"))
print(re.findall('ab{3,5}?',"abbbbbbbbcd"))    #这里的5碰上?就相当于没用了

输出:

['a']
['ab']
['a']
['abbb'] 

三、捕获组

先说说什么是捕获组?

捕获组就是一个可以让你从一个字符串中提取出多个有用的子字符串的东西

简单来说呢,就是把我们找出来的字符串分成一个一个组。

捕获组,就是我们用( )括起来的东西,这样就被提取为了一个单独的“组”

多说无用,来看一个代码:

import re
print(re.findall(r'\w+:\d+',"Alex:1994,Sunny:1996"))
print(re.findall(r'(\w+):\d+',"Alex:1994,Sunny:1996"))
print(re.findall(r'(\w+):(\d+)',"Alex:1994,Sunny:1996"))

依次输出:
['Alex:1994', 'Sunny:1996']
['Alex', 'Sunny']
[('Alex', '1994'), ('Sunny', '1996')]

解释:

第一行:\w+:\d+意思是查找格式为  字符:数字  的字符

第二行:(\w+):\d+ 加上括号后,就将\w+捕获成一个组了,此时就只会输出被捕获的字符

第三行:(\w+):(\d+)都加上括号,就捕获了两个组,所以只输出捕获的两个组,我们可以看到相必第一个,此时没有了冒号


当然,以上只是捕获组的简单用法,稍后在re模块中,我们再详细介绍它。 

四、re模块

调用方法:import re

(1)re库函数一览

(2)具体用法示例

1.re.findall(pattern,string,flags)

解释:

pattern:正则表达式或要匹配的字符

string:一大串字符串内容

flags:一些参数,可以达成如忽略大小写进行匹配等的目的。

上文都是用这个函数的,这里不过多论述。

这里主要说说flags参数,它有如下几个参数:

使用时,可写成诸如 re.findall(r'ab*',"abbbbbbbbcd",re.I)

2.re.compile(pattern,[flags])

它主要是可以将正则表达式对象复用,避免了每次调用时都重新编译正则表达式,提高了效率。

import re
# 编译正则表达式
pattern = re.compile(r'\d+')
# 使用编译后的正则表达式对象进行匹配
result = pattern.findall('There are 123 apples and 45 bananas.')
print(result) 

输出:

['123', '45']

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

解释:

pattern:正则表达式或要匹配的字符

string:一大串字符串内容

flags:同1中的参数

这里它其实和re.findall的用法是一样的,唯一不同的是:

  • re.match() 只检查字符串的起始部分,如果起始部分与正则表达式匹配,返回一个匹配对象。
  • re.findall() 会扫描整个字符串,返回所有符合正则表达式的部分,返回一个包含所有匹配项的列表。

比如:

result = re.match(r'\d+','apples 123')
print(result)  # 输出 None

 tips:哪是起始部分,看的是空格哦

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

参数原理同re.match和re.findall一样。

而re.search与他们不同的是:扫描整个字符串,查找第一个匹配的子串。如果找到匹配,返回一个匹配对象;如果没有匹配,返回 None

5.group 和 groups 函数

先说group()

它用于返回匹配到的整个字符串。

参数默认为 0,表示获取整个字符内容。

参数为1,则表示获取第一个捕获组  (没错,它又出现了,上文三中有解释哦)

参数为2,则表示获取第二个捕获组

……

参数为n,则表示获取第n个捕获组

当然,如果获取不存在的捕获组,就会报错。

比如,我们先设定好如下代码:

import re
pattern =r"(\w+)\s(\w+)"
string = "Hello World"

我们可以看到,上面的代码中有两个捕获组,然后输入下面的代码:

print(re.search(pattern, string).group())
print(re.search(pattern, string).group(1))
print(re.search(pattern, string).group(2))

输出:

Hello World        #默认参数为0,输出整个匹配到的字符
Hello                  #参数为1,输出1个捕获组
World                 #参数为2,输出2个捕获组

再说groups( )

它跟group()不同的是,groups()不管参数是几,都将捕获组全部给你以元组形式返回来

如果没有捕获组,group()会报错,而groups()会返回一个空元组。

比如,我们继续输入代码:

import re
pattern =r"(\w+)\s(\w+)"
string = "Hello World"
print(re.search(pattern, string).groups())
print(re.search(pattern, string).groups(2))

输出:

('Hello', 'World')
('Hello', 'World')

6.re.sub(pattern,replace,string,count=0,flags=0)

功能:使用一个字符串替换正则表达式匹配到的内容

pattern:正则表达式或要匹配的字符

replace:替换匹配字符串的字符串

string:一大串字符串内容

count:匹配的最大替换次数

flags:同前文解释

简单来说,就是替换字符用的,直接看代码:

import re
print(re.sub(':','-',"Alex:1994,Sunny:1996"))
print(re.sub(':','-',"Alex:1994,Sunny:1996",1))

输出:

Alex-1994,Sunny-1996
Alex-1994,Sunny:1996

解释:

第一个print里,意思是将“:”替换成“-”然后输出

第二个print里,因为后面有一个1,所以意思是将一个“:”替换成“-”然后输出

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

功能:按正则表达式匹配内容,切割目标字符串

pattern:正则表达式或要匹配的字符

string:一大串字符串内容

maxsplit:最大分割数,剩余部分作为最后一个元素输出

flags:同前文

比如下面代码: 

import re
print(re.split(r'\d{6}', 'BIT100081 TSU100084'))
print(re.split(r'\d{6}', 'BIT100081 TSU100084',1))

输出:

['BIT', ' TSU', ' ']
['BIT', ' TSU100084']

解释:

第一个print:意思是,匹配6次数字并删除掉

第二个print:意思是,仅在第一个组里,匹配6次数字并删掉

tips:各位可能发现,输出的最后多了一个‘ ’,这是为啥呢?

答:这是因为匹配到数字后,re.split() 会将匹配部分删除,并在其位置插入空字符串。如果字符串的结尾部分没有其他字符,那么在 re.split() 后会产生一个额外的空字符串。


致此,正则表达式讲解完毕~!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣打卡12:复原IP地址

链接&#xff1a;93. 复原 IP 地址 - 力扣&#xff08;LeetCode&#xff09; 这道题需要对字符串进行操作&#xff0c;我选择了三层循环&#xff0c;其实还可以递归。 我在循环时进行了剪枝&#xff0c;比如一些情况直接跳出循环。 我的代码&#xff1a; class Solution { p…

说下JVM中一次完整的GC流程?

大家好&#xff0c;我是锋哥。今天分享关于【说下JVM中一次完整的GC流程&#xff1f;】面试题。希望对大家有帮助&#xff1b; 说下JVM中一次完整的GC流程&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在JVM中&#xff0c;垃圾回收&#xff08;GC&am…

vs配置c++标准

在 vcxproj 文件中添加 <LanguageStandard>stdcpp17</LanguageStandard> 和在 Visual Studio 属性页面中设置 “C语言标准” 为 “ISO C17 标准 (/std:c17)” 是完全等价的。 它们的对应关系是&#xff1a; VS属性页面中的设置&#xff1a; 项目 -> 属性 ->…

TcpServer 服务器优化之后,加了多线程,对心跳包进行优化

TcpServer 服务器优化之后&#xff0c;加了多线程&#xff0c;对心跳包进行优化 TcpServer.h #ifndef TCPSERVER_H #define TCPSERVER_H#include <iostream> #include <winsock2.h> #include <ws2tcpip.h> #include <vector> #include <map> #…

风控大讲堂|游戏黑产情报挖掘与治理

您的产品有没有遇到过被薅羊毛了&#xff1f;网络游戏行业的繁荣&#xff0c;催生了一批围绕游戏而生的职业玩家&#xff0c;他们利用多开、修改器等手段&#xff0c;疯狂薅游戏资源&#xff0c;破坏游戏经济平衡&#xff0c;给游戏公司带来了难以估量的巨大损失。那么针对此类…

最近邻搜索 - 经典树型结构 M-Tree

前言 如果你对这篇文章感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 最近邻搜索的目标是从 N N N 个对象中&#xff0c;快速找到距离查询点最近的对象。根据需求的不同&#xff0c;该任务又分…

Jmeter进阶篇(30)深入探索 JMeter 监听器

前言 在性能测试领域里,Apache JMeter 是一款经典而强大的工具,而其中的监听器(Listeners)组件更是发挥着不可或缺的关键作用。 监听器就像敏锐的观察者,默默记录测试执行过程中的各种数据,作为系统性能分析的数据依据。 本文将带你全方位走进 JMeter 监听器的奇妙世界,…

uni-app 个人课程表页面

uni-app 个人课程表页面 插件参考地址 大部分代码都是参考了上述代码&#xff0c;只对代码做出了优化 1. 页面模板 在 schedule.vue 文件中&#xff0c;编写页面结构&#xff1a; <template><view><u-navbar title"个人中心"><view class&q…

ElementEye,网页分析器

介绍 我们经常使用Python写爬虫&#xff0c;爬到网页数据之后&#xff0c;就需要用beautifulSoup进行解析。因为写爬虫并不是我的主营工作&#xff0c;大多数只是用来分析一下想要的数据而已&#xff0c;所以经常会忘记beautifulSoup的用法。 同时&#xff0c;我们总是分析页面…

【Compose multiplatform教程】01 创建你的多平台项目 <官网搬运>

这是 “创建带有共享逻辑和用户界面的 Compose 多平台应用” 教程的第一部分。 第一步&#xff1a;创建你的多平台项目 第二步&#xff1a;探究可组合代码 第三步&#xff1a;修改项目 第四步&#xff1a;创建你自己的应用程序 在这里&#xff0c;你将学习如何使用 Kotlin 多平…

使用OpenTK展示3D点云图像(C#)

最近在研究3D显示&#xff0c;找到一款在winform上展示3D点云的控件&#xff0c;并且实现了点线面的展示&#xff0c;及光照渲染纹理贴图等功能&#xff0c;如下面几张图所展示。 一些基础知识可以在LearnOpenTK - OpenTK 这个网站上学习到。 我这边使用的是openTK3.3.3版本&a…

李宏毅机器学习-批次 (batch)和动量(momentum)

一.batch&#xff08;批次&#xff09; 在计算微分时&#xff0c;不是对所有的数据算出来的Loss值做微分&#xff0c;而是将所有的数据分成一个一个的batch。一个batch是一个B&#xff0c;在更新参数时&#xff0c;拿B的资料计算Loss&#xff0c;计算gradient&#xff0c;再更新…

洗鞋小程序(源码+文档+部署+讲解)

本文将深入解析“洗鞋小程序”的项目&#xff0c;探究其架构、功能以及技术栈&#xff0c;并分享获取完整源码的途径。 系统概述 为洗鞋提供服务&#xff0c;包含小程序和管理端。 本项目名称为洗鞋小程序&#xff0c;是一个基于小程序的在线洗鞋平台。该系统提供下单、订单管…

【数据结构】二叉树的性质和存储结构

性质 在二叉树的第i层上至多有2^{i-1}个结点,至少有1个结点 深度为k的二叉树至多有2^{k-1}个结点&#xff08;k≥1&#xff09;&#xff0c;至少有k个结点 对任何一棵二叉树T&#xff0c;如果其叶子数为n0&#xff0c;度为2的结点数为n2&#xff0c;则n0n21 具有n个结点的完…

交换排序(Swap Sort)详解

交换排序Swap Sort详解 冒泡排序冒泡算法代码实现冒泡分析 快速排序快排算法代码实现快排分析 交换类排序主要是通过两两比较待排元素的关键字&#xff0c;若发现与排序要求相逆&#xff0c;则交换之。在这类排序方法中最常见的是起泡排序&#xff08;冒泡排序&#xff09;和快…

MySQL追梦旅途之性能优化

1、索引优化 索引可以显著加速查询操作&#xff0c;但过多或不适当的索引也会带来负面影响&#xff08;如增加写入开销&#xff09;。因此&#xff0c;选择合适的索引至关重要。 创建索引&#xff1a; 为经常用于WHERE子句、JOIN条件和ORDER BY排序的列创建索引。 CREATE I…

小程序IOS安全区域优化:safe-area-inset-bottom

ios下边有一个小黑线&#xff0c;位于底部的元素会被黑线阻挡 safe-area-inset-bottom 一 用法及作用&#xff1a; IOS全面屏底部有小黑线&#xff0c;位于底部的元素会被黑线阻挡&#xff0c;可以使用以下样式&#xff1a; .model{padding-bottom: constant(safe-area-ins…

矩阵的乘(包括乘方)和除

矩阵的乘分为两种&#xff1a; 一种是高等代数中对矩阵的乘的定义&#xff1a;可以去这里看看包含矩阵的乘。总的来说&#xff0c;若矩阵 A s ∗ n A_{s*n} As∗n​列数和矩阵 B n ∗ t B_{n*t} Bn∗t​的行数相等&#xff0c;则 A A A和 B B B可相乘&#xff0c;得到一个矩阵 …

解决阿里云轻量级服务器 Ubuntu 24.04.1 LTS 没网也 ping 不通 8.8.8.8 以及 route -n 没有输出任何转发信息

事情发生在两天前&#xff0c;位于公网的阿里云轻量级服务器&#xff08;Ubuntu 24.04.1 LTS&#xff09;忽然没网。主要是上次上服务器进行配置已经是一个多月前&#xff0c;最近也没有做什么事情&#xff0c;就忽然没网了&#xff0c;让人纳闷。更主要的是&#xff0c;上次备…

Cesium中实现仿ArcGIS三维的动态图层加载方式

Cesium 加载 ArcGIS 动态图层的方式 如果你在 Cesium 中加载过 ArcGIS 的动态图层&#xff0c;你会发现&#xff0c;Cesium 对于动态图层仍然采用类似切片图层的逻辑进行加载。也就是每个固定的瓦片 export 一张图片。 这样会造成一些问题&#xff1a; 请求量大&#xff0c;…