Python正则表达式常用梳理

目录

[1、 什么是正则表达式.

[2、 正则表达式语法结构.

[2.1. 入门案例:了解正则表达式.

[2.3. python中的正则表达式模块re
[2.3.1 字符串查询匹配的函数:

[2.3.2 字符串拆分替换的函数:

[2.4. 正则表达式中的元字符.

[2.5. 正则表达式中的量词.

[2.6. 正则表达式中的范围匹配.

[2.7. 正则表达式中的分组.

[2.8. 正则表达式中的特殊用法.

[2.9 正则表达式的贪婪模式和懒惰模式.

1.什么是正则表达式

正则表达式:也称为规则表达式,英文名称Regular Expression, 我们在程序中经常会缩写为 regex 或者 regexp, 专门用于进行文本检索、匹配、替换等操作的一种技术,
注意:正则表达式是一种独立的技术,并不是某编程语言独有的

正则表达式,是一种特殊的符号,这样的符号是需要解释才能使用的,也就是需要正则表达式引擎来进行解释,目前正则表达式的引擎主要分三种:DFA,NFA,POSIX NFA/ 有兴趣了解正则表达式引擎的童鞋,可以自己查看资料。

2.正则表达式语法结构

接下来,我们开始了解这样一个神秘的可以类似人类神经网络一样思考问题的技术的语法结构
注意:我们通过python程序进行测试,但是正则表达式的语法结构在各种语言环境中都是通用的。

2.1入门案例:了解正则表达式

我们通过一个简单的案例入手:通常情况下,我们会验证用户输入的手机号码是否合法,是否 156/186/188开头的手机号码,如果按照常规验证手段,就需要对字符串进行拆分处理,然后逐步匹配
重要提示:python中提供了re模块,包含了正则表达式的所有功能,专门用于进行正则表达式的处理;
案例:

def validatephone(phone):
#定义正则表达式,python中的正则表达式还是一个字符串,是以 r 开头的字符串
regexp = r"^(156|186|188)\d{8}$"
#开始验证
if re.match(regexp,phone):
    return "手机号码合法”
else:
    return "手机号码只能以156/186/188开头,并且每一个字符都是数字,请检查"
#开始验证
print(validatephone(userphone))

执行上面的代码,我们得到正常验证的结果,大家可以自己试一试,
使用正则表达式之后会使程序变得非常简洁,接下里,我们继续正则表达式的表演

2.3python中的正则表达式模块re

2.3.1字符串查询匹配的函数:

函数                                               描述
re ,match(reg, info)      用于在开始位置匹配目标字符串info中符合正则表达式reg的字符,匹配成功会返回一个match对象,匹配不成功返回None

re, search(reg,info)    扫描整个字符串info,使用正则表达式reg进行匹配,匹配成功返回匹配的第一个match对象,匹配不成功返回None

re,findall(reg,info)    扫描整个字符串info,将符合整个表达式reg的字符全部提取出来存放在列表中返回

re , fullmatch(reg,info)   扫描整个字符串,如果整个字符串都包含在正则表达式表示的范围中,返回整个字符串,否则返回None

re, finditer(reg,info)   扫描整个字符串,将匹配到的字符保存在一个可以遍历的列表中

参考官方re.py源代码如下:


image.png

image.png

2.3.2字符串拆分替换的函数:

函数                                      描述
re.split(reg,string)       使用指定的正则表达式reg匹配的字符,将字符串string 拆分成一个字符串列表,如:re.split(r."\s+",info),表示使用一个或者多个空白字符对字符串info进行拆分,并返回一个拆分后的字符串列表

re,sub(reg,repl,string)  只用指定的字符串repl来替换字符串string中匹配正则表达式reg的字符

接下来,我们进入正则表达式干货部分

2.4正则表达式中的元字符

在使用正则表达式的过程中,一些包含特殊含义的字符,用于表示字符串中一些特殊的位置非常重要,我们先简单了解一下一些常用的元字符

元字符                                    描述
^                表示匹配字符串的开头位置的字符
$               表示匹配字符串的结束位置的字符
.                 表示匹配任意一个字符
\d              匹配一个数字字符
\D              匹配一个非数字字符
\s               匹配一个空白字符
\S               匹配一个非空白字符
\w                匹配一个数字/字母/下划线中任意一个字符
\W                匹配一个非数字字母下划线的任意一个字符
\b                 匹配一个单词的边界
\B                      匹配不是单词的开头或者结束位置

上干货:代码案例

导入正则表达式模块
import re
#定义测试文本字符串,我们后续再这段文本中查询数据
msg1 = '''pyhton is an easy to learn, powerful programming language.
it has efficient high-level data  structures and a simple but effective approach to object-oriented programming.
python'selegant syntax and dynamic typing,together with its interpreted nature,
make it an ideal language for scripting and rapid application development in many areas on most platforms.
'''
msg2 = 'hello'
msg3 = 'hello%'
#定义正则表达式,匹配字符串开头是否为pyhton
regStart = r"efficient"
#从字符串开始位置匹配,是否包含符合正则表达式的内容,返回匹配到的字符串的match对象
print(re.match(regStart,msg1))
#扫描整个字符串,是否包含符合正则表达式的内容,返回匹配到的第一个字符串的match对象
print(re.search(regStart,msg1))
#扫描整个字符串,是否包含符合正则表达式的内容,返回匹配到的所有字符串列表
print(re,findall(regStart,msg1))
#扫描整个字符串,是否包含符合正则表达式的内容太,返回匹配到的字符串的迭代对象
for r in re.finditer(regStart ,msg1):
print("->"+ r.group())
#扫描整个字符串,是否包含在正则表达式匹配到的内容中,是则返回整个字符串,否则返回None
print(re.fullmatch(r"\w*",msg2))
print(re,fullmatch(r"\w*",msg3))
上述代码执行结果如下:
None
<sre.SRE_MATCH object;span=(66,75)match = 'efficient'>
['efficient']
->efficient
<sre.SRE_Match object; span = (0,5),match = 'hello'>
None

2.5正则表达式中的量词

正则表达式中的量词,是用于限定数量的特殊字符

量词                                         描述
x*                   用于匹配符号*前面的字符出现0次或者多次
x+                 用于匹配符号+前面的字符出现1次或者多次
x?                   用于匹配符号?前面的字符出现0次或者1次
x{n}                  用于匹配符号{n}前面的字符出现n次
x{m,n}             用于匹配符号{m,n}前面的字符出现至少m次,最多n次
x{n,}                     用于匹配符号{n,}前面的字符出现至少n次

接着上代码干货:


image.png

image.png

2.6.正则表达式中的范围匹配

在正则表达式中,针对字符的匹配,出了快捷的元字符的匹配,还有另一种使用方括号进行的范围匹配方式,具体如下:

范围                                    描述
[0-9]   用于匹配一个0~9之间的数字,等价于\d
[^0-9]  用于匹配一个非数字字符,等价于\D
[3-6]   用于匹配一个3~6之间的数字
[a-z]   用于匹配一个a~z之间的字母
[A-Z]   用于匹配一个A~Z之间的字母
[a-f]   用于匹配一个a~f之间的字母
[a-zA-Z]    用于匹配一个a~z或者A-Z之间的字母,匹配任意一个字母
[a-zA-Z0-9] 用于匹配一个字母或者数字
[a-zA-Z0-9_]    用于匹配一个字母或者数字或者下划线,等价于\w
[^a-zA-Z0-9_]   用于匹配一个非字母或者数字或者下划线,等价于\W

注意:不要使用【0-120】来表示0~120之间的数字,这是错误的,整理测试代码如下:


image.png

2.7.正则表达式中的分组

正则表达式主要是用于进行字符串检索匹配操作的利器,在一次完整的匹配过程中,可以将匹配到的结果进行分组,这样就更加的细化了我们队匹配结果的操作
正则表达式通过圆括号()进行分组,以提取匹配结果的部分结果
常用的两种分组

分组                                      描述
(expression)         使用圆括号直接分组;正则表达式本身匹配的结果就是一个组,可以通过group()或者group(0)获取;然后正则表达式中包含的圆括号就是按照顺序从1开始编号的小组
(?P<name>expression)    使用圆括号分组,然后给当前的圆括号表示的小组命名为name,可以通过group(name) 进行数据的获取
image.png

image.png

image.png

2.8.正则表达式中的特殊用法

使用分组的同,会有一些特殊的使用方式如下:


同时

2.9正则表达式的贪婪模式和懒惰模式

在某些情况下,我们匹配的字符串出现一些特殊的规律是,就会出现匹配结果不尽如人意的意外情况
如:在下面的字符串中,将div标签中的所有内容获取出来
如:在下面的字符串中,将div标签中的所有内容获取出来
<div>内容1</div><p>这本来是不需要的内容</p><div>内容2</div>
此时,我们想到的是,使用<div>作为关键信息进行正则表达式的定义,如下
regexp = r"<div>.*</div>"
本意是使用上述代码来完成div开始标签和结束标签之间的内容匹配,但是,匹配的结果如下
<div> [内容1</div><p>这本来是不需要的内容</p><div>内容2] </div>
我们可以看到,上面匹配的结果,是将字符串开头的<div>标签和字符串结束的</div>当成了匹配元素,对包含在中间的内容直接进行了匹配,也就得到了我们期望之外的结果:
内容1</div><p>这本来是不需要的内容</p><div>内容2
上述就是我们要说的正则表达式的第一种模式:贪婪模式
贪婪模式:正则表达式匹配的一种模式,速度快,但是匹配的内容会从字符串两头向中间搜索匹配(比较贪婪~),一旦匹配选中,就不继续向字符串中间搜索了,过程如下:
开始:<div>内容1</div><p>这本来是不需要的内容</p><div>内容2</div>

第一次匹配:【<div>内容1</div><p>这本来是不需要的内容</p><div>内容2</div>】

第二次匹配<div>【内容1</div><p>这本来是不需要的内容</p><div>内容2】</div>

匹配到正则中需要的结果,不再继续匹配,直接返回匹配结果如下:
内容1</div><p>这本来是不需要的内容</p><div>内容2
明显贪婪模式某些情况下,不是我们想要的,所以出现了另一种模式:懒惰模式
懒惰模式:正则表达式匹配的另一种模式,会首先搜索匹配正则表达式开始位置的字符,然后逐步向字符串的结束位置查找,一旦找到匹配的就返回,然后接着查找
regexp = r"<div>.*?</div>"
开始:<div>内容1</div><p>这本来是不需要的内容</p><div>内容2</div>

第一次匹配:【<div>】内容1</div><p>这本来是不需要的内容</p><div>内容2</div>

第二次匹配【<div>内容1</div>】<p>这本来是不需要的内容</p><div>内容2</div>

匹配到正则中需要的结果:内容1

继续向后查找

第三次匹配<div>内容1</div>【<p>这本来是不需要的内容</p>】<div>内容2</div>

第四次匹配<div>内容1</div><p>这本来是不需要的内容</p>【<div>内容2</div>】

匹配到正则中需要的结果:内容2

查找字符串结束!
正则表达式匹配的两种模式:贪婪模式、懒惰模式
贪婪模式:从目标字符串的两头开始搜索,一次尽可能多的匹配符合条件的字符串,但是有可能会匹配到不需要的内容,正则表达式中的元字符、量词、范围等都模式是贪婪匹配模式,使用的时候一定要注意分析结果,如:<div>.</div>就是一个贪婪模式,用于匹配<div>和</div>之间所有的字符
懒惰模式:从目标字符串按照顺序从头到位进行检索匹配,尽可能的检索到最小范围的匹配结果,语法结构是在贪婪模式的表达式后面加上一个符号?即可,如<div>.
?</div>就是一个懒惰模式的正则,用于仅仅匹配最小范围的<div>和</div>之间的内容
不论贪婪模式还是懒惰模式,都有适合自己使用的地方,大家一定要根据实际需求进行解决方案的确定

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容