Python之路(第二十一篇) re模块
一、re模块
正则表达式本身是一种小型的、高度专业化的编程语言,正则表达式就是字符串的匹配规则,在多数编程语言里都有相应的支持,python里对应的模块是re,正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
匹配语法
re方法(匹配模式,字符串,flag)
(一)字符
1、元字符
普通字符 | 匹配内容 |
---|---|
. | 匹配任意除换行符"\n"外的字符,若指定flag DOTALL,则匹配任意字符,包括换行 |
\ | 转义字符,使后一个字符改变原来的意思 |
* | 匹配前一个字符0或多次 |
+ | 匹配前一个字符1次或无限次 |
? | 匹配一个字符0次或1次, 和防止贪婪匹配 |
^ | 匹配字符串开头。在多行模式中匹配每一行的开头,^元字符如果写到[]字符集里就是反取 |
$ | 匹配字符串末尾,在多行模式中匹配每一行的末尾 |
| | 或。匹配|左右表达式任意一个,从左到右匹配,如果|没有包括在()中,则它的范围是整个正则表达式 |
{} | {m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次 |
[] | 字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。abc表示取反,即非abc。所有特殊字符在字符集中都失去其原有的特殊含义。用\反斜杠转义恢复特殊字符的特殊含义。 |
() |
被括起来的表达式将作为分组,从表达式左边开始没遇到一个分组的左括号“(”,编号+1.分组表达式作为一个整体,可以后接数量词。表达式中的|仅在该组中有效。 匹配任何在圆括号内的正则表达式, 并表明分组的开始和结束; 分组的内容在完成匹配后可以提取出来,而且可以在后面的字符串中用特殊的number 序列匹配
|
量词
量词
|
用法说明
|
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
元字符匹配次数说明
例子
import re# '.'字符 , 从开头一直找 ,返回找到的所有字符print(re.findall("nichol..","nicknicholas")) #['nicholas']#'^'匹配字符串开头。在多行模式中匹配每一行的开头print(re.findall("^nick","nickcalnicholas")) #['nick']#'$'匹配字符串末尾,在多行模式中匹配每一行的末尾print(re.findall("ick$","nicholasnicknick")) #['ick']# '*' 匹配*号前的字符0次或多次print(re.findall("a*","abcabaad")) #['a', '', '', 'a', '', 'aa', '', '']# '+' 匹配前一个字符1次或多次print(re.findall("a+","abcabaad")) #['a', 'a', 'aa']# '?' 匹配前一个字符1次或0次print(re.findall("a?","abcabaad")) #['a', '', '', 'a', '', 'a', 'a', '', '']# '|' 或。匹配|左右表达式任意一个,从左到右匹配,如果|没有包括在()中,则它的范围是整个正则表达式print(re.findall("(ab|AC)","abcadxyzab")) #['ab', 'ab']print(re.findall("(ab|AC)","ACxyznick")) #['AC']# '{m}'匹配前一个字符m次,{m,n}匹配前一个字符m至n次,若省略n,则匹配m至无限次print(re.findall("a{2,4}","abcaadaxyzaaaa")) #['aa', 'aaaa']# '[]'字符集。对应的位置可以是字符集中任意字符。字符集中的字符可以逐个列出,也可以给出范围,如[abc]或[a-c]。print(re.findall("[ac]","acxyzabc")) #['a', 'c', 'a', 'c']print(re.findall("[^ac]","acxyzabc")) #['x', 'y', 'z', 'b']print(re.findall('a[bc]d','acd')) #['acd']print(re.findall('[a-z]','acd')) #['a', 'c', 'd']print(re.findall('[1-9]','45dha3')) #['4', '5', '3']print(re.findall('[^ab]','45bdha3')) #['4', '5', 'd', 'h', '3']print(re.findall('[\d]','45bdha3')) #['4', '5', '3']# '()'匹配被括起来的内容print(re.findall("(ab)",'xyz453d6gab89uzaxby')) #['ab']print(re.findall("(ab)",'xyz453d6gab89uzaby')) #['ab', 'ab']print(re.findall(r'(ad)+', 'addhahdwha2e3adadad')) #['ad', 'ad']
2、预定义字符集
预定义字符 | 匹配说明 |
---|---|
\d | 数字:[0-9] 字符英文说明digit |
\D |
等同于非数字:[^0-9]
|
\s | 匹配任意的空白符:[<空格>\t\r\n\f\v] 可以匹配空格、换行符、缩进符号等 . 字符英文说明space |
\S |
非空白字符:[^\s]
|
\w | 匹配包括下划线在内的任何字字符:[A-Za-z0-9_](大小写的A-Z,数字0-9) 字符英文说明word |
\W | 匹配非字母字符,即匹配特殊字符 |
\A | 仅匹配字符串开头,同^ |
\Z | 仅匹配字符串结尾,同$ |
\b | 匹配\w和\W之间,即匹配单词边界匹配一个单词边界,也就是指单词和空格间的位置。例如, 'lo\b' 可以匹配"hello" 中的 'lo',但不能匹配 "hellohi" 中的 'lo'。 |
\B | [^\b]匹配所有的非边界字符 |
例子
import re# 匹配数字:[0-9]print(re.findall("\d","你好我11大22,求十大3")) #['1', '1', '2', '2', '3']#匹配非数字[0-9]print(re.findall("\D","你好我11大22,求十大3")) #['你', '好', '我', '大', ',', '求', '十', '大']# 匹配任意的空白符(打印不出来的)print(re.findall("\s","你好我好\n,大家好\t")) #['\n', '\t']# 匹配非空白字符:[^\s]print(re.findall("\S","你好我好\n,大家好\t")) #['你', '好', '我', '好', ',', '大', '家', '好']# 匹配包括下划线在内的任何字字符:[A-Za-z0-9_](大小写的A-Z,数字0-9),python中支持中文print(re.findall("\w","ni好2_,大家好,HI\n")) #['n', 'i', '好', '2', '_', '大', '家', '好', 'H', 'I']# 仅匹配字符串开头,同^print(re.findall("\Ah","hell hello")) #['h']# 仅匹配字符串结尾,同$print(re.findall("o\Z","hellhello")) #['o']# \b匹配\w和\W之间,即匹配单词边界匹配一个单词边界,也就是指单词和空格间的位置。print(re.findall("\\b","hello word")) #['', '', '', ''] 把两个单词左右的空格边界匹配到了这里多加一个斜杠是为了转义print(re.findall(r"\b","hello word")) #['', '', '', ''],或者不转义直接加r
3、字符集[]
字符集 | 说明 |
---|---|
[0-9]
|
也可以用-表示范围,[0-9]就和[0123456789]是一个意思` |
[a-z]
|
同样的如果要匹配所有的小写字母,直接用[a-z]就可以表示 |
[A-Z]
|
[A-Z]就表示所有的大写字母 |
[0-9a-fA-F]
|
可以匹配数字,大小写形式的a~f,用来验证十六进制字符 |
[A-z]
|
可以匹配所有的大写字母和小写字母 |
例子
import reprint(re.findall("[0-9]+","add1ab21cc332ab")) #['1', '21', '332']print(re.findall("[2-9]+","add1ab21cc332ab")) #['2', '332']print(re.findall("[a-z]+","aadddccda")) #['aadddccda']print(re.findall("[c-z]+","aadddcacda")) #['dddc', 'cd']print(re.findall("[A-z]","A,BC,abc")) #['A', 'B', 'C', 'a', 'b', 'c']
4、()元字符,分组
也就是分组匹配,()里面的为一个组也可以理解成一个整体
如果()后面跟的是特殊元字符如 (adc)* , 那么*控制的前导字符就是()里的整体内容,不再是前导一个字符
例子
import reprint(re.findall("(ab)+","addabccab")) #['ab', 'ab']
5、r原生字符
将在python里有特殊意义的字符如\b,转换成原生字符(就是去除它在python的特殊意义),不然会给正则表达式有冲突,为了避免这种冲突可以在规则前加原始字符r,或者加上转义符\
例子
print(re.findall("\\b","hello word"))
print(re.findall(r"\b","hello word"))
r是real的意思
6、注意
(1) ^有两种用法,一种是作为开头,表示匹配字符串开头。第二种是非,在字符集里用表示非
如[^0-9]
表示匹配非数字0-9
(2)在正则表达式中,有很多有特殊意义的是元字符,比如\d和\s等,如果要在正则中匹配正常的"\d"而不是"数字"就需要对"\"进行转义,变成'\'。
在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。所以如果匹配一次"\d",字符串中要写成'\d',那么正则里就要写成"\\d",这样就太麻烦了。这个时候我们就用到了r'\d'这个概念,此时的正则是r'\d'就可以了。
(3)注意^和$使用所在的位置。匹配开头^要在被匹配的字符前面即“^a”,匹配结尾 $要在被匹配的字符后面即"a$"
正则 | 待匹配字符 | 匹配结果 | 说明 |
---|---|---|---|
\d | \d | False |
因为在正则表达式中\是有特殊意义的字符,所以要匹配\d本身,用表达式\d无法匹配
|
\d | \d | True |
转义\之后变成\\,即可匹配
|
"\\d" | '\d' | True |
如果在python中,字符串中的'\'也需要转义,所以每一个字符串'\'又需要转义一次
|
r'\d' | r'\d' | True |
在字符串之前加r,让整个字符串不转义
|
7、贪婪匹配与非贪婪匹配
*?, +?, ??, {m,n}?
前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配,加上?变成非贪婪匹配(惰性匹配)
正则 | 待匹配字符 | 匹配结果 | 说明 |
---|---|---|---|
<.*> | <script>...<script> | <script>...<script> |
默认为贪婪匹配模式,会匹配尽量长的字符串
|
<.*?> | <script>...<script> | <script><script> |
加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串
|
例子
import reprint(re.findall("<.*>","<script>...<script>")) #['<script>...<script>']print(re.findall("<.*?>","<script>...<script>")) #['<script>', '<script>']
分析:<.*>是贪婪匹配,从左直接匹配到最右侧,然后向左回退到最后一个“>”,这就是回溯算法
"<.*?>"是非贪婪匹配,匹配时是从左向右匹配,遇到一个“>”马上返回,继续匹配,遇到一个遇到一个“>”马上返回。
几个常用的非贪婪匹配Pattern
*? 重复任意次,但尽可能少重复+? 重复1次或更多次,但尽可能少重复?? 重复0次或1次,但尽可能少重复{n,m}? 重复n到m次,但尽可能少重复{n,}? 重复n次以上,但尽可能少重复
.*?的用法
. 是任意字符* 是取 0 至 无限长度? 是非贪婪模式。何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:.*?x就是取前面任意长度的字符,直到一个x出现
(二)re模块中常用功能函数
1、compile()
编译正则表达式模式,返回一个对象的模式。(可以把那些常用的正则表达式编译成正则表达式对象,这样可以提高一点效率。)
格式
re.compile(pattern,flags=0)
pattern: 编译时用的表达式字符串。
flags 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。常用的flags有:
标志 | 含义 |
---|---|
re.S(DOTALL) | 使.匹配包括换行在内的所有字符 |
re.I(IGNORECASE) | 使匹配对大小写不敏感 |
re.L(LOCALE) | 做本地化识别(locale-aware)匹配,法语等 |
re.M(MULTILINE) | 多行匹配,影响^和$ |
re.X(VERBOSE) | 该标志通过给予更灵活的格式以便将正则表达式写得更易于理解 |
re.U | 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B |
例子
import rep = re.compile("\d+") #创建一个常用的规则res = p.search("abc123sxajk")print(res) #search直接返回的是一个match对象,需要调用group()方法获取匹配字符串print(res.group())
输出结果
<_sre.SRE_Match object; span=(3, 6), match='123'>123
2、search()
函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
格式
re.search(pattern, string, flags=0)
例子
import reres = re.search("\d+","abc123sxajk")print(res) #search直接返回的是一个match对象,需要调用group()方法获取匹配字符串print(res.group())
输出结果
<_sre.SRE_Match object; span=(3, 6), match='123'>123
3、match()
同search,不过仅在字符串开始处进行匹配
格式:
re.match(pattern, string, flags=0)
例子
import reres = re.match("\d+","123sxajk")print(res) #match匹配要从开头处匹配,match也是直接返回的是一个match对象,需要调用group()方法获取匹配字符串print(res.group()) #如果匹配不到返回的是None,这时调用group()方法会报错
输出结果
<_sre.SRE_Match object; span=(0, 3), match='123'>123
分析:match()方法是从字符串的开头处匹配的,如果匹配不到则返回None,这时调用group()方法会报错,因为None没有group()方法。
*注:match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
group() 返回被 RE 匹配的字符串
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元组包含匹配 (开始,结束) 的位置
group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。
a. group()返回re整体匹配的字符串,a. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常a.groups()groups() 方法返回一个包含正则表达式中所有小组字符串的元组,从 1 到所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元素就是正则表达式中定义的组。
4、findall()
返回所有满足匹配条件的结果,放在列表里
格式:
re.findall(pattern, string, flags=0)
import reprint(re.findall("a","abc sxa dda"))
输出结果
['a', 'a', 'a']
5、finditer()
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。找到 RE 匹配的所有子串,并把它们作为一个迭代器返回。
格式:
re.finditer(pattern, string, flags=0)
import reres = re.finditer("\d","dak2fhr34ehnb567grd")print(res) #返回的是一个可调用的迭代器print(type(res))print(next(res)) #通过迭代器的next()方法取出每个值,这里的每个值是一个match对象print(next(res).group()) #通过调用match对象的group()方法来取出匹配出的值
输出结果
<callable_iterator object at 0x02655870><class 'callable_iterator'><_sre.SRE_Match object; span=(3, 4), match='2'>3
6、split()
按照能够匹配的子串将string分割后返回列表。
格式:
re.split(pattern, string[, maxsplit])
import reprint(re.split("[ab]","abcdeg"))
输出结果
['', '', 'cdeg']
分析:
执行过程:首先以"a"分割字符串“abcdeg",得到结果["","bcdeg"],即一个空白字符和”bcdeg“,然后再用”b“对这个结果再次进行分割,得到['', '', 'cdeg'],即两个空白字符和‘cdeg’.
7、sub()
使用re替换string中每一个匹配的子串后返回替换后的字符串。
格式:
re.sub(pattern, repl, string, count)
例子
import reprint(re.sub("a","s","hahahah"))
输出结果
hshshsh
8、subn()
替换string中匹配子串,但返回的是元组(替换的结果,替换了多少次)
格式:
subn(pattern, repl, string, count=0, flags=0)
例子
import reprint(re.subn("a","s","hahahah"))
输出结果
('hshshsh', 3)
三、重要补充
1、findall的分组优先
如果re.findall()规则里有分组(括号),那么findall只能返回分组里的内容。
例子
res = re.findall("www.(baidu|google).com","www.google.com")print(res)
输出结果
['google']
分析:注意这里只能匹配返回出分组里的内容,而非整体的字符串。
想要整体返回需要在分组里加?:取消分组优先模式(问号在正则表达式里的第三个功能,第一个表示匹配次数,第二个是实现惰性匹配)
import reres = re.findall("www.(?:baidu|google).com","www.google.com")print(res)
输出结果
['www.google.com']
2、 split的优先级
re.split()方法在加上分组之后可以返回被匹配分割去掉的项
例子
import reres1 = re.split("\d+","hello5world5hi2")res2 = re.split("(\d+)","hello5world5hi2")print(res1)print(res2)
输出结果
['hello', 'world', 'hi', '']['hello', '5', 'world', '5', 'hi', '2', '']
转载于:https://www.cnblogs.com/Nicholas0707/p/9115933.html
Python之路(第二十一篇) re模块相关推荐
- Python之路(第二十篇) subprocess模块
一.subprocess模块 subprocess英文意思:子进程 那什么是进程呢? (一)关于进程的相关理论基础知识 进程是对正在运行程序的一个抽象,进程的概念起源于操作系统,是操作系统最核心的概念 ...
- Python之路(第十七篇)logging模块
一.logging模块 (一).日志相关概念 日志是一种可以追踪某些软件运行时所发生事件的方法.软件开发人员可以向他们的代码中调用日志记录相关的方法来表明发生了某些事情.一个事件可以用一个可包含可选变 ...
- Python之路(第二十三篇) 面向对象初级:静态属性、静态方法、类方法
一.静态属性 静态属性相当于数据属性. 用@property语法糖装饰器将类的函数属性变成可以不用加括号直接的类似数据属性. 可以封装逻辑,让用户感觉是在调用一个普通的数据属性. 例子 class R ...
- Python之路(第二十七篇) 面向对象进阶:内置方法、描述符
一.__call__ 对象后面加括号,触发执行类下面的__call__方法. 创建对象时,对象 = 类名() :而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()( ...
- Python之路【第一篇】:Python简介和入门
Python之路[第一篇]:Python简介和入门 Python简介 Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗 ...
- Python开发【第十一篇】:JavaScript
Python开发[第十一篇]:JavaScript JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏 ...
- 奋斗的小孩系列 FPGA学习altera系列: FPGA学习altera 系列 第二十一篇 数码管设计
奋斗的小孩系列 FPGA学习altera系列: FPGA学习altera 系列 第二十一篇 数码管设计 作者:奋斗的小孩 郝旭帅(转载请注明出处) 大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是 ...
- Python爬虫学习第十一天---pymongo模块使用
Python爬虫学习第十一天-pymongo模块使用 一.安装pymongo模块 python3 -m pip install pymongo 二.pymongo模块的使用 1.配置基础项 user ...
- 原创:《Python之路实战40篇》PDF高清版,限时下载!
内容简介 1 <Python之路40篇实战 .pdf>包含Python篇.数据分析篇.机器学习篇等 3 大模块,目录如下: 下载方式 2 关注公众号「Python与算法社区」,后台回复一个 ...
最新文章
- Dreamweaver——如何使网页中的第一个DIV水平居中
- 使用Qt Designer编辑资源
- 利用kinect检测任意平面
- SQL-Server使用点滴(二-系统表)
- git多系统协作时换行符问题
- python 点云配准_点云的全局配准
- 【C004】VB - 数据文件(一)顺序文件
- 微软 android 输入法下载官网下载地址,微软五笔输入法官网下载_微软王码五笔输入法8689版官方下载-华军软件园...
- 为什么材料专业要劝退?材料专业就找不到好工作吗?
- WINDOWS XP数字总线补丁 KB888111
- 程序员 做头发 奇遇记
- 来客在线客服系统源码 支持一键安装
- MySQL查询——为表和字段取别名
- 电容容量越大越好吗?
- 编译x86 release版本libcurl,支持https
- python求合数的所有因子,0是素数吗(python求一个数的因子)
- 2020年中科院软件所夏令营经历
- 2023计算机毕业设计SSM最新选题之java农产品售卖系统31u5z
- Python3网络爬虫快速入门实战解析
- 配置SD卡ext文件系统启动
热门文章
- 注释转换——(小项目)
- 奔跑吧2015,个推一月活动走起
- UIScrollView用法
- 用yui compressor 压缩 javascirpt脚本
- 服务器系统ghost版 raid,服务器在raid5下做系统ghost备份.docx
- 英文句子改写在线软件_试完这些英文论文写作辅助神器,你会发现新大陆der~...
- Kali Linux重新支持RTL8814au芯片
- ​HealthKit开发快速入门教程大学霸内部教程
- 配置JDKAndroid 2D游戏引擎AndEngine
- vs mfc数据与控件绑定错了_如何进行数据趋势分析?VS扩展工具——C1迷你图控件了解一下...