python 正则表达式 前瞻_正则表达式 For Python-程序员宅基地

技术标签: python 正则表达式 前瞻  

Manarola

正则表达式有很多流派,也有很多的特性,不同的语言支持度也是不一样的。本篇文章是写Python中的正则表达式的用法的,介绍了一些可用特性,也指出了某些特性是不支持的。

本篇文章仅为学习笔记,不对正则表达式做深入研究,只想用最短的时间入门正则。

实践是检验真理的唯一标准。你以为的并不是你以为的,如有问题还是要写一个例子用多个工具验证下最好。

字符组 [ ]

在同一位置可能出现的各种字符,也可以称之为字符集。

写法有很多种。有原始写法,然后是范围表示法,然后是排除型字符组,然后是字符组简记法,最后还有一个字符组运算(Python不支持)。

[3645970128] --> [0123456789] --> [0-9] --> \d

[0-9A-Za-z_] --> [\dA-Za-z_] --> \w

"-"用来表示范围 范围的确定依靠码值来确定,一般据ASCⅡ表值。

排除型字符组由脱字符"^"来指定,"^"排在第一位,紧靠在"["之后,需要排除的按上面写法写在"^"之后。

[^0-9] # 排除数字,也可以写成[^\d]

如果需要排除"-",则必须将"-"写在开头"^"之后,如果一定要写在后面,则必须用"\"转义。

字符组简记

说明

\d

数字(digit) [0-9]

\w

单词(word) [0-9A-Za-z_] 字母数字下划线

\s

空白(space) [ \t\r\n\f\v] 空格、制表符、回车、换行等显示空白字符

\D 、\W 、\S是与之对应的排除型字符组简记。

以上说的\d 、\w 、\s的匹配规则都是针对ASCⅡ编码规则而言的,也叫ASCⅡ匹配规则。在Unicode编码中,全角数字0、1、2之类的也算数字,也可以由\d匹配;中文字符也可以算是单词字符,由\w匹配;同样全角空格也由\s匹配。

Python3默认采用Unicode匹配规则,但也可以显示指定采用ASCⅡ匹配规则(表达式最开始用(?a)指定ASCⅡ模式)。

另外还有一个POSIX字符组(POSIX Character Class)。POSIX(Portable Operating System Interface for uniX),它是含有正则表达式规范的一系列规范。这种字符组只在java、php、ruby中支持,经过测试以及查阅资料并没有显示Python是支持的,不过也有可能是POSIX字符组需要变化一下才能使用,就像其他语言那样。

量词

以上说的都是匹配单个字符,如果多了怎么办。所以就出现了量词。

量词限定之前的元素的出现,这个元素可能是一个字符,也可能是一个字符组,还可以是一个表达式。

一般形式量词

说明

{n}

之前的元素必须出现n次

{m,n}

之前的元素最少出现m次,最多出现n次

{m,}

之前的元素最少出现m次,最高没有限制

{0,n}

之前的元素可以不出现,也可以出现,最多出现n次

常用量词

等价形式

说明

*

{0,}

可能出现,也可能不出现,出现次数没有上限

+

{1,}

至少出现1次,最多没有限制

?

{0,1}

可以不出现,也可以就出现1次

所有的量词默认都是贪婪量词,能匹配的,绝不停止匹配。它会优先尝试匹配,并记下这个状态,以便将来反悔。这个返回的过程称之为回溯。

量词也可以变成懒惰的,称之为懒惰量词,能不匹配就不匹配,如果之后的表达式匹配失败,则会回溯进行匹配。变成懒惰量词是在现有量词后加上?。

还有一种量词称之为占有量词。它和贪婪量词很像,但是占有量词不会进行回溯,优点是速度快,但是失败也会很快。变成占有量词是在现有量词后加上+。

分组 ( )

分组,顾名思义就是将某些东西分成一组,对外来看是一个整体。通过()将表达式括起来,此时表达式就是一个整体一个可整体操作的元素。括号内的表达式称之为“子表达式”。

多选结构

多选结构的形式是(···|···),在括号中以竖线|分隔开多个子表达式,这些子表达式也叫多选分支;在一个多选结构中,多选分支的数目没有限制。在匹配时,整个多选结构被视为单个元素,只要某个子表达式能够匹配,整个多选结构的匹配就成功。

一般而言ab|cd依旧是多选结构,等价于(ab|cd),建议使用后者,更加明确,也能够避免一些错误。例如^ab|cd$其实是(^ab|cd$)而不是^(ab|cd)$,因为竖线|的优先级很低。

多选结构的匹配顺序问题。比如表达式(aaa|aaabbb)去匹配aaabbb,匹配结果到底是aaa还是aaabbb呢?Python中多选结构都会优先选择最左侧的分支,所以匹配出来是aaa。不过在实际使用中请避免这种情况,分支中存在重复会大大增加回溯的计算量。

引用分组

分组之后,正则表达式会保存每一个分组真正匹配的文本(不是正则表达式可匹配的文本),匹配完成后,可通过编号进行引用当时捕获的内容。

如果出现多个嵌套括号,那编号的计数规则是怎样的呢?首先整个正则表达式默认存在一个的编号为0的分组,其他分组的编号是依据从左到右开括号出现的顺序决定的,第几个括号就是第几组。

反向引用

在正则表达式内部引用之前的捕获分组匹配的文本,之前捕获分组中锚点表示的位置信息不会被保留下来。

引用形式:\num,其中num表示所引用分组的编号。

sub替换中引用

re.sub(pattern,replacement,string),在replacement中使用引用分组。引用形式同样是:\num。

匹配结果中group引用

对匹配完成后,可对匹配结果对象调用group(num)获取分组中匹配的数据。

\num引用的二义性问题:\10是第10个引用还是第1个引用后再加一个0呢?

Python中将其解释为第10个引用,可通过\g,消除二义性。

注:反向引用只引用之前的捕获分组匹配的文本,之前捕获分组中的锚点表示的位置信息不会被保留下来。

命名分组

鉴于数字编号不够直观,并且括号多了难免混淆,所以就有了命名分组的出现。Python中用(?P...)来分组,其中name是分组的名称。

反向引用必须使用(?P=name)来引用;替换则需要写作\g;匹配结果中则使用group(name)。

非捕获分组

无论是否需要分组,只要出现了括号,正则表达式再匹配的时候就会把括号内的子表达式存储起来,提供引用。如果并不需要引用,保存这些信息无疑会影响正则表达式的性能。

正则表达式提供了非捕获分组(?:...),这样的括号叫做非捕获型括号,他只能限定量词的作用范围,不捕获任何文本。在引用分组时,分组的编号同样会按照开括号出现的顺序从左到右计数,非捕获分组会略过。

原子分组

另一种非捕获分组就是原子分组(?>...)。这种分组可以将回溯操作关闭,但它只针对原子分组内的部分,而不针对整个正则表达式。经过测试发现这个表达式?>是不识别的。但是一篇文章(英文原版)给出了一个等价方案:

可以通过使用零宽度先行assert((?= RE))来模拟它,它从当前点匹配相同的语义想要,将一个命名的组((?P RE))放在lookahead中,然后使用一个命名的反引用((?P = name)恰恰是零宽度断言匹配.组合在一起,这给了你相同的语义,代价是创建一个额外的匹配组和很多语法.

匹配模式

所谓匹配模式,指的是匹配时使用的规则。设定特定的模式,可能会改变对正则表达式的识别,也可能会改变正则表达式中字符的匹配规定。常用的匹配模式一共有4种:不区分大小写模式、单行模式、多行模式、注释模式。通常有两种指定方式:以模式修饰符指定(?modifier),或者以预定义的常量作为特殊参数传入来指定。

Python中模式修饰符只要出现,无论在什么位置,都对整个正则表达式生效。Python中不支持失效修饰符(?-modifier)。

不区分大小写模式

不区分大小写模式的修饰符是i (case Insensitive),则(?i)it可以匹配的有it It iT IT。

单行模式

修饰符是s (Single line)。

这种模式下所有的文本只在一行里,换行符只是其中一个普通字符。单行模式影响的是点号.的匹配规则。

多行模式

修饰符是m (Multiline)。

多行模式影响的是^和$的匹配规则。

注释模式

修饰符是x (eXtended mode 扩展模式)。

有时正则表达式可能非常复杂,不但难于编写和阅读,也难以维护。python中支持使用(?#comment)的记法添加注释;还有一种是使用注释模式,此时正则表达式对应的字符串可以跨越多行,注释则以#comment的形式添加在正则表达式内部,每一条注释从#开始,到行末结束,同时还可以使用缩进表示层级结构更加方便阅读和维护。

断言

常见的断言有三类:单词边界、行起始/结束位置、环视。断言并不真正的匹配文本,他匹配的是位置,他只负责判断在某个位置左/右侧的文本是否符合要求。

单词边界

单词边界记为\b,他匹配的是“单词边界”位置,而不是字符。也就是说\b能够匹配这样的位置:一边是单词字符,另一边不是单词字符(包括没有字符)。不同的模式下\w不同,所以\b也就不同。

另外还有\B非单词边界。

行起始/结束为位置

^匹配字符串开始的位置。

$匹配字符串结束的位置。

前面已经说了:多行模式影响的是^和$的匹配规则。

在不指定多行模式的情况下:^匹配的是整个字符串的开始位置,$匹配的是整个字符串的结束位置。

当在多行模式下:^匹配的是字符串的起始位置以及换行之后行终止符之后的位置,如果字符串末尾出现了行终止符,则依旧匹配行终止符之后的那个位置;$匹配的是字符串的结束位置,但是这个位置是在字符结束之后行终止符之前的位置。

python中还有一个特殊标记\Z,它和$类似,但是他不受多行模式的影响,\Z不管行终止符,他匹配的是整个字符串的结束位置,在行终止符之后的位置。

^和$的另一个特点是在进行正则表达式替换的时候并不会被替换。也就是说,在起始和结束位置进行替换,只会在起始和结束位置添加一些字符,位置本身依然存在。

环视

环视是对匹配字符周围字符的验证,他匹配的并不是字符,而是位置。

环视大致分为以下四种:

名称

又称

说明

肯定顺序环视

正前瞻

...(?=...)

否定顺序环视

反前瞻

...(?!...)

肯定逆序环视

正后顾

(?<=...)...

否定逆序环视

反后顾

(?

肯定环视和否定环视的区别就是:肯定环视要想判断成功,字符串中必须有字符由环视结构中的表达式匹配;而否定环视要判断成功却有两种情况1.字符串的字符不能匹配2.根本就没有字符,这个位置可能是起始或结束位置。

环视的组合:

包含

环视中包含环视,这个和环视的并列还不太一样,这个外层环视是限定的位置,但是这个内层环视是限定外层环视的。(?=...(?!...))

多环视并列

环视的并列要求每一个环视对当前位置的匹配都必须成功,而各个环视之间是没有任何联系的,他们都将作用于该位置。

环视作为多选分支

将若干个环视作为多选分支排列在多选结构中,只要有一个环视分支成立,整个多选就成立。

分组的编号只与捕获型括号相关,而不受其他任何括号类型的影响,所以环视结构的括号并不影响分组。但是环视结构中出现了捕获型括号,则会影响分组。

环视结构中的捕获型括号一旦匹配完成,就不能回溯。e.g.(?<=(\d+))\w+\1无法在123a12中找到匹配。

Python支持顺序环视,但对于逆序环视,Python只支持匹配固定长度文本表达式。(?<=dogs?)和(?<=(dog|cats))都是不合法的,遇到这样的可与选择多选结构来改造,但是如果出现*和+之类的量词,就不能用多选了。

至此,整个正则表达式部分就介绍完毕,以下部分Python正则API。

Python中的正则表达式模块是re模块,通过import re 导入re模块来使用正则表达式。

在正则表达式中,大多数的函数是类似re.search(pattern,string)的形式,其中pattern通常是正则表达式的字符串,这可以视为“静态方法”。其实也可以将RegexObject对象作为pattern参数传入,或者直接对RegexObject对象调用相同名字的成员方法,结果相同,但是后面这两个方法可以显示的缓存RegexObject对象。

除了正则表达式对象RegexObject,还有一个MatchObject对象,MatchObject对象提供了一些方法和属性,通过他们可以获取匹配的信息。

方法

描述

注释

start(n)

返回编号为n的捕获分组匹配的开始位置,如果对应分组不存在或者未匹配,则返回-1

如果没有设定n,则返回整个表达式匹配的开始位置,此时n等于0

pos

返回整个表达式匹配的开始位置

end(n)

返回编号为n的捕获分组匹配的结束位置,如果对应分组不存在或未匹配,则返回-1

如果没有设定n,则返回整个表达式匹配的结束位置,此时n等价于0

endpos

返回整个表达式匹配的结束位置

等价于end(0)

group(n)

返回编号为n的捕获分组匹配的文本

如果没有设定n,则返回整个表达式匹配的文本,此时n等价于0

groups()

返回各捕获分组匹配的文本构成的tuple

如果表达式中不存在捕获分组,则返回空tuple

span(n)

返回编号为n的捕获分组匹配的开始-结束位置

如果没有设定n,则返回整个表达式匹配的开始-结束位置,此时n等价于0

re

返回匹配时所使用的正则表达式对象

lastindex

返回匹配成功的编号最大的捕获分组的编号

如果没有,则返回None

string

返回用来尝试用正则表达式来匹配的字符串

expand(str)

返回一个字符串,可以在其中引用捕获分组匹配的文本

re.compile(regex [, flags])

这个方法用于显示“编译”正则表达式对象。如果需要多次使用同一个正则表达式,那么每次使用编译好的正则表达式对象比每次临时编译表达式对象要快得多。另外compile()还有一个功能,那就是添加第二个参数re.DEBUG来观察整个正则表达式的详细信息。

re.search(pattern, string [, flags])

这个方法用来测试正则表达式pattern能否在string中找到匹配,flags是可选参数是匹配模式(aiLmsux)的按位OR结果。如果能找到匹配,则返回MatchObject,否则返回None。

re.match(pattern, string [, flags])

re.match()和re.search()非常相似,参数相同,返回值也行通,非常容易混淆,唯一的区别在于:如果re.match()匹配成功,那么pattern匹配的字符串必须开始于string的最左端。也就是说,re.match()只会在字符串的开始的位置尝试匹配,re.search()则没有这个限制。MULTILINE 多行模式下,match也只匹配string的开头部分。

re.findall(pattern, string [, flags])

这个函数会一次性的找出正则表达式pattern在string中的所有匹配,返回一个list。

如果pattern中存在捕获分组,则返回list的元素并非整个表达式所匹配的文本,而是各个捕获分组所匹配文本构成的tuple。返回的tuple中是没有默认的分组编号0所匹配的文本元素的,如果需要返回可以在整个正则表达式外再加一个括号。tuple中文本的顺序就是分组编号的顺序。

re.finditer(pattern, string [, flags])

如果文本内容很多,使用re.findall()一次性找到所有匹配的成本可能很高,使用re.finditer()可以返回一个迭代器(iterator),他可以按照从左到右的顺序逐个遍历每次匹配的MatchObject对象,依次进行处理或检验。

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

这个函数用正则表达式pattern能够匹配的文本切分字符串string。如果正则表达式在开头或者结尾位置找到匹配,那么结果的开头或结尾会出现空字符串。也可以明确设定maxsplit。在Python中这个参数表示切分的次数。也就是说,返回数组一般会包含maxsplit+1个元素。如果maxsplit设定负数,则表示不做任何切分;若设定0,则等于没有设定;若设定的值为正数,且小于实际可切分的次数,则按设定的值进行切分,若大于实际可切分的次数,则以实际可切分的次数为准。

re.sub(patern ,repl, string [, count=0, flags=0])

这个函数用来进行正则表达式替换,它将字符串string中的正则表达式pattern能够匹配的文本替换为repl指定的文本。如果要在replacement字符串中引用之前的某个捕获分组匹配的文本,则应该使用\num。Python中也提供了跟清晰的方式在repl中引用分组,写作\g,这种记法也可以使用命名分组\g。repl也可以是一个函数,他接受一个MatchObject对象,返回一个String对象。也可以设定count参数,他指定替换操作最多能发生的次数。

re.subn(patern ,repl, string [, count=0, flags=0])

与sub()相同,但返回一个元祖,其中包含新字符串和替换次数。

re.escape(string)

返回一个字符串,其中所有的非字母数字字符都带有反斜杠。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39533432/article/details/111721862

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签