《Python 3 程序开发指南》 学习笔记

13.1 Python的正则表达式语言

13.1.1 字符与字符类

特殊字符:\.^$?+*{}|

在一个字符类内部,除\外,特殊字符不再具备特殊意义.

当^ 为一个字符类的第一个字符时,表其特殊含义否定。

-表示一个字符范围,如果作为字符类中的第一个字符,就表示一个字面意义上的连字符。

字符类速记(表)

符号 含义
. 可以匹配除换行符之外的任意字符,或带re.DOTALL标记的任意字符,或匹配字符内部的字面意义的字符。
\d 匹配一个Unicode数字,或带(等价于的意思?)re.ASCII标记的[0-9]
\D 匹配一个Unicode非数字,或带re.ASCII标记的[0-9]
\s 匹配Unicode空白,或带re.ASCII标记的[\t\n\r\f\v]
\S 匹配Unicode非空白,或带re.ASCII标记的[^\t\n\r\f\v]
\w 匹配一个Unicode单词字符,或带re.ASCII标记的[a-zA-Z0-9]
\W 匹配一个Unicode非单词字符,或带re.ASCII标记的[^a-zA-Z0-9]

13.1.2 量词 {m, n} ? + *

{m, n}:m表示该量词必须匹配的最小次数,而n表示最多次数,如e{1,1}, e{2, 2}

如果m, n相同,可以简写为{m}。而量词{0,1}有一种速记形式?.

travell{0,1}ed == travell?ed

正则表达式量词(表)

语法 含义
e? or e{0,1} 贪婪地匹配表达式e的0或1次出现
e?? or e{0,1}? 非贪婪地匹配表达式e e+或{1,}的0次或1次出现,贪婪地匹配表达式e的1次或多次出现
e+? or e{1,}? 非贪婪地匹配表达式e的一次或多次出现
e* or e{0,} 贪婪地匹配表达式e的0次或1次出现
e*? or e{0,}? 非贪婪地匹配表达式e地0次或1次出现
e{m} 准确匹配表达式e的m次出现
e{m,} 贪婪地匹配表达式e的至少m次出现
e{m,}? 非贪婪地匹配表达式e的至少m次出现
e{,n} 贪婪地匹配表达式e的至多n次出现
e{,n}? 非贪婪地匹配表达式e的至多n次出现
e{m,n} 贪婪地匹配表达式e的至少m次,至多n次出现
e+ e{1,n}(至少一次),n是量词地可能地最大值,通常是32767
e* e{0,n}(任意次),n同上
e{m,n}? 非贪婪地匹配表达式e地至少m次,至多n次出现
  • 默认情况下,所有量词都是贪婪的,量词后面跟随?表示非贪婪。
re.match(r"\d+", "136")
#<re.Match object; span=(0, 3), match='136'>
re.match(r"\d+?", "136")
#<re.Match object; span=(0, 1), match='1'>
re.match(r"\d??", "136")
#<re.Match object; span=(0, 0), match=''>
re.match(r"\d{0,1}?", "136")
#<re.Match object; span=(0, 0), match=''>
re.match(r"\d{0,1}?36", "136")
#<re.Match object; span=(0, 3), match='136'>
re.match(r"\d*?", "136")
#<re.Match object; span=(0, 0), match=''>
re.match(r"\d*?6", "136")
#<re.Match object; span=(0, 3), match='136'>
re.match(r"<img\s+[^>]*?src=\w[^>]*?>", "<img src=dd>")
#<re.Match object; span=(0, 14), match='<img src=dd>'>

组与捕获 ?:可以关闭捕获

()可以进行分组,而交替字符|在多种方案中选取一个的情况下使用。

re.match(r"aircraft|airplane|jet", "airplane")
#<re.Match object; span=(0, 8), match='airplane'>
re.match(r"air(craft|plane)|jet", "airplane")
#<re.Match object; span=(0, 8), match='airplane'>

()在分组的同时进行捕获,以备后用。

for i in range(3):
print(re.match(r"(air(craft|plane)|jet)", "airplane")[i])
#airplane #只要匹配成功,首项都是完整匹配项
#airplane
#plane try:
for i in range(3):
print(re.match(r"(air(?:craft|plane)|jet)", "airplane")[i]) #?:关闭捕获
except IndexError as err:
print("IndexError: {0}".format(err))
#airplane
#airplane
#IndexError: no such group
s = "eric1 = something\n"\
"eric2 = somewhere\n"\
"eric3 = somebody"
try:
for i in range(10):
print(re.match(r"(\w+ = .+\n?)+", s)[i])
except IndexError as err:
print("IndexError: {0}".format(err)) #eric1 = something
#eric2 = somewhere
#eric3 = somebody
#eric3 = somebody
#IndexError: no such group
s = "eric1 = something\n"\
"eric2 = somewhere\n"\
"eric3 = somebody"
try:
for i in range(10):
print(re.match(r"(?:(\w+) = (.+)\n?)+", s)[i])
except IndexError as err:
print("IndexError: {0}".format(err)) #eric1 = something
#eric2 = somewhere
#eric3 = somebody
#eric3
#somebody
#IndexError: no such group

反向引用 \i 反向引用不能用在字符类内部,即不能用在[]中

re.match(r"(\w+)\s+\1", "eric eric")
#<re.Match object; span=(0, 9), match='eric eric'>
re.match(r"(\w+)(\d?)\s+\1\2", "eric1 eric1")
#<re.Match object; span=(0, 11), match='eric1 eric1'>
re.match(r"(\w+)(\d?)\s+\1\2", "eric1 eric2") # None

命名捕获 (?P...) 反向引用:(?P=name)

  • 注意, (?P=name)只是匹配,((?P=name))才能完成捕获
for item in ('name', 'what'):
print(re.match(r"(?P<name>\w+)\s+(?P<what>\w+)", "Pikachu Pokemon")[item])
#Pikachu
#Pokemon
re.match(r"(?P<name>\w+)\s+((?P=name))", "Pikachu Pikachu")[2]
#'Pikachu'

断言与标记

符号 含义
^ 在起始处匹配,也可以在带MULTILINE标记的每个换行符后匹配
$ 在结尾处匹配,也可以在MULTILINE标记的每个换行符前匹配
\A 在起始处匹配
\b 在单词边界匹配,受re.ASCII标记影响——在字符类内部,则是backspace字符的转义字符
\B 在非单词边界匹配,受re.ASCII标记影响
\Z 在结尾处匹配
(?=e) 如果表达式e在此断言处匹配,但没有超越此处——称为前瞻或正前瞻,则匹配
(?!e) 如果表达式e在此前言处不匹配,也没有超越此处——称为负前瞻,则匹配
(?<=e) 如果表达式e恰在本断言之前匹配——成为正回顾,则匹配
(?<!e) 如果表达式e恰在本断言之前不匹配——称为负回顾,则匹配
  • 单词边界,顾名思义就是该位置为单词的边界,比如\b位置之前是一个单词,后面是非单词(比方空格),当然反过来也是可以的。
re.match(r"eric", "eric1")
#<re.Match object; span=(0, 4), match='eric'>
re.match(r"eric\b", "eric1") #None
re.match(r"deric", "deric1")
#<re.Match object; span=(0, 5), match='deric'>
re.match(r"d\beric", "deric1") #None
s = "I'm sorry, my son.\n Actually, actually, she is my daughter, and your sister..."
re.match(r".+(?<=son)", s)
#<re.Match object; span=(0, 17), match="I'm sorry, my son">
s = "I'm sorry, my son.\n Actually, actually, she is my daughter, and your sister..."
re.match(r".+(?<!daugther)", s)
#<re.Match object; span=(0, 18), match="I'm sorry, my son.">

条件性匹配 (?(id)yes_exp) | (?(id)yes_exp|no_exp)

s1 = "src=\"ddd.ddd\""
s2 = "src='ddd.ddd'"
s3 = "src=ddd.ddd"
re.match(r"src=([\"'])([^\"'>]+)\1", s1) # ! s3
#<re.Match object; span=(0, 13), match='src="ddd.ddd"'>
re.match(r"src=([\"'])?([^\"'>]+)(?(1)\1)", s3)
#<re.Match object; span=(0, 11), match='src=ddd.ddd'>

设置标记 (?flags) flags == a | i | m| s | x

符号 含义
a re.ASCII
i re.IGNORECASE
m re.MULTILINE
s re.DOTALL
x re.VERBOSE

13.2 正则表达式模块

正则表达式模块的函数(表)

语法 描述
re.compile(r, f) 返回编译后的正则表达式r,如果指定,就将其标记设置为f
re.escape(s) 返回字符串s,其中所有非字母数字的字符都是用反斜线进行了转义处理,因此返回的字符串中没有特殊的正则表达式字符
re.findall(r, s, f) 返回正则表达式r在字符串s中所有非交叠的匹配(如果给定f,就受其值约)。如果正则表达式中有捕获,那么每次匹配都作为一个捕获元组返回
re.finditer(r, s, f) 对正则表达式r在字符串s中每个非交叠的匹配(如果给定f,就受其值约),都返回一个匹配对象
re.match(r, s, f) 如果正则表达式r在字符串s的起始处匹配(如果给定f,就受其制约),就返回一个匹配对象,否则返回None
re.search(r, s, f) 如果正则表达式r在字符串s的任意位置处匹配(如果给定f,就受其值约),就返回一个匹配对象,否则返回None
re.split(r, s, m) 返回分割字符串s(在正则表达式r每次出现出进行分割)所产生的字符串的列表,至多分割m次(如果没有给定m,就分割尽可能多的次数),如果正则表达式中包含捕获,就被包含在分割的部分之间
re.sub(r, x, s, m) 对正则表达式r的每次匹配(如果给定m,那么至多m次),返回字符串s的一个副本,并将其替换为x——这可以是一个字符串,也可以是一个函数
re.subn(r, x, s, m) 与re.sub()函数相同,区别在于此函数返回一个二元组,其中一项为生成的字符串,一项为代入的次数
import re
re.escape("\\") #'\\\\'
s = "eric1 = something\n"\
"eric2 = somewhere\n"\
"eric3 = somebody"
try:
for i in range(10):
print(re.findall(r"(?:(\w+) = (.+)\n?)+", s)[i])
except IndexError as err:
print("IndexError: {0}".format(err))
#('eric3', 'somebody')
#IndexError: list index out of range #从下面的例子可以明白什么是非交叠匹配
s = "bigbigericbigbig\n"\
"smallsmallericsmallsmall\n"\
"hardharderichardhard"
e = r"""(?x)(?i)
((?P<attr>big|small)(eric)\2)
"""
e = re.compile(e)
re.findall(e, s) #[('bigericbig', 'big', 'eric'), ('smallericsmall', 'small', 'eric')]
s = "eric1 = something\n"\
"eric2 = somewhere\n"\
"eric3 = somebody"
re.split(r"\n", s)
#['eric1 = something', 'eric2 = somewhere', 'eric3 = somebody']

正则表达式模块的标记(表)

标记 含义
re.A or re.ASCII 使\b,\B,\s,\S,\w,\W都假定字符串为ASCII,默认为这些字符类的速记法,依赖于Unicode规范
re.I or re.IGNORECASE 使正则表达式以大小写不敏感的方法进行匹配
re.M or re.MULTILINE 使^在起始处并在每个换行符后匹配,使$在结尾处但在每个换行符之前匹配
re.S or re.DOTALL 使.匹配每个字符,包括换行符
re.X or re.VERBOSE 使空白和注释包含在匹配中
s = "eric1=something\n"\
"eric2 = somewhere\n"\
"Eric3 = somebody"
re.findall(r"eric", s, re.I)
#['eric', 'eric', 'Eric']
e = r"""(?x)
(?P<eric>eric)
"""
e = re.compile(e)
e.findall(s)
#['eric', 'eric']

正则表达式对象方法(表)

rx表正则表达式,下面的方法其实上面都有提到过。

语法 描述
rx.findall(s, start, end) 返回字符串s中(或s的start:end分片中)正则表达式的所有非交叠的匹配,如果正则表达式有捕获,那么每次匹配是返回一个捕获元组
rx.finditer(sstart, end) 对字符串s中(或s的start:end分片中)的每个非交叠匹配,返回一个匹配对象
rx.flags 正则表达式编译时设置的标记 readonly
rx.groupindex 一个字典,其键位捕获组名,值为捕获组编号,如果没有使用名称就为空
rx.match(s, start, end) 如果正则表达式在字符串s的起始处(或s的start:end分片起始处)匹配,就返回一个匹配对象,否则返回None
rx.pattern 正则表达式被编译时使用的字符串
rx.search(s, start, end) 如果正则表达式在字符串s的任意位置(或s的start:end分片中的任意位置)匹配,就返回一个匹配对象,否则返回None
rx.split(s, m) 返回字符串列表,其中每个字符串都源自对字符串s的分割(在正则表达式的每次匹配处),但至多有m个分割(如果没有给定m,则可以有尽可能多的分割);如果正则表达式有捕获,就包含在列表中俩个分割之间
rx.sub(x, s, m) 返回字符串s的副本,其中每个(或至多m个,如果给定)匹配出使用x(可以时字符串或函数)进行替换
rx.subn(x, s, m) 与rx.sub()相同,区别在于返回的是二元组,其中一项时结果字符串,一项时所做替换的个数
e.groupindex
#mappingproxy({'eric': 1})
e.pattern
#'(?x)\n (?P<eric>eric)\n'

匹配对象的属性与方法(表)

m 匹配对象——finditer, match等方法可能返回匹配对象

语法 描述
m.end(g) 返回组g(如果给定)在文本中匹配的终点索引位置,对组0,则表示整体匹配;如果匹配中不包含改组,就返回-1
m.endpos 搜索的终点索引位置(文本的重点,或赋予match()或search()的end
m.expand(s) 返回字符串s,并将其中的捕获标志(\1, \2, \g等类似的标志)用相应的捕获替代 经测试如果s== r"..."上述可行,如果s是普通的字符串,应当用:\1, \2, \g,没错除了\g外需要转义
m.group(g, ...) 返回编号的或命名的组g,如果给定的不止一个,就返回相应的捕获组成的元组(组0表示整体匹配)
m.groupdict(default) 返回一个字典,其中存放所有命名的捕获组,组名作为键,捕获作为值;如果给定了default参数,就将其用作那些不参与匹配的捕获组的值
m.groups(default) 返回包含所有捕获组的元组,从1开始;如果给定default,就将其用作那些不参与匹配的捕获组的值
m.lastgroup 匹配的,编号最高的捕获组的名称,如果不存在或没使用名称,就返回None
m.lastindex 匹配的,编号最高的捕获组的编号,如果没有就返回None
m.pos 搜索的起始索引位置(文本的起始处,或赋予match()或search()的start)
m.span(g) 如果给定g,就返回组g在文本中匹配的起始索引位置与结尾索引位置(对组0,则是整体匹配);如果改组不参加匹配,就返回(-1,-1)
m.start(g) 如果给定g,就返回组g在文本中匹配的起始索引位置(对组0,则是整体匹配);如果改组不参加匹配,就返回01
m.string 船体给match()或search()的字符串
s = "bigbigericbigbig\n"\
"smallsmallericsmallsmall\n"\
"hardharderichardhard"
e = r"""(?x)(?i)
((?P<attr>big|small)(eric)\2)
"""
e = re.compile(e)
ms = re.finditer(e, s)
for m in list(ms):
print(m.end(2), m.endpos)
#6 62
#27 62
s2 = "\g<attr>pig"
s3 = "\\2cat"
s4 = r"\2cat"
ms = re.finditer(e, s)
print(next(ms).expand(s2))
m = next(ms)
print(m.expand(s3), m.expand(s4))
#bigpig
#smallcat smallcat
m.group(), m.group(1), m.group(1, 2, 3)
#('smallericsmall', 'smallericsmall', ('smallericsmall', 'small', 'eric'))
m.groupdict()
#{'attr': 'small'}
m.groups()
#('smallericsmall', 'small', 'eric')
m.lastgroup #None
m.lastindex #1
m.span(), m.span(1), m.span(2), m.span(3)
#((22, 36), (22, 36), (22, 27), (27, 31))
m.string
#'bigbigericbigbig\nsmallsmallericsmallsmall\nhardharderichardhard'

Python Revisited Day 13 (正则表达式)的更多相关文章

  1. Python学习:13.Python正则表达式

    一.正则表达式简介 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式. 就其本质 ...

  2. Python标准库01 正则表达式(re包)

    python正则表达式基础 简单介绍 正则表达式并不是python的一部分.正则表达式是用于处理字符串的强大工具,拥有自己独特的语法及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大 ...

  3. python基础之 re(正则表达式)模块学习

    今天学习了Python中有关正则表达式的知识.关于正则表达式的语法,不作过多解释,网上有许多学习的资料.这里主要介绍Python中常用的正则表达式处理函数. re.match re.match 尝试从 ...

  4. python字符串转义与正则表达式特殊字符转义

    最近在自学python,字符串和正则表达式的特殊字符转义有点混淆,做个笔记简单总结一下. 1.普通字符串转义 在字符串中使用特殊字符时,要用反斜杠(\)转义字符.例如:'Let\'s go!',这里对 ...

  5. python爬虫之re正则表达式库

    python爬虫之re正则表达式库 正则表达式是用来简洁表达一组字符串的表达式. 编译:将符合正则表达式语法的字符串转换成正则表达式特征 操作符 说明 实例 . 表示任何单个字符 [ ] 字符集,对单 ...

  6. python与JavaScript中正则表达式如何转换

    使用python爬取网站数据的时候,总会遇到各种各样的反爬虫策略,有很大一部分都和JavaScript(以下简称为JS) 有关.在破解这些JS代码的过程中,经常会遇到模拟JS正则表达式的情况,因此,今 ...

  7. Python编程中 re正则表达式模块 介绍与使用教程

    Python编程中 re正则表达式模块 介绍与使用教程 一.前言: 这篇文章是因为昨天写了一篇 shell script 的文章,在文章中俺大量调用多媒体素材与网址引用.这样就会有一个问题就是:随着俺 ...

  8. python基础之坑爹正则表达式

    python基础之坑爹正则表达式 概述 re模块就是python语言中的正则表达式,拆出来单独写一条blog是因为正则表达式本身就是比较庞大的知识,写具体些让自己以后方便查找. IP: ^(25[0- ...

  9. 【Python开发】Python之re模块 —— 正则表达式操作

    Python之re模块 -- 正则表达式操作 这个模块提供了与 Perl 相似l的正则表达式匹配操作.Unicode字符串也同样适用. 正则表达式使用反斜杠" \ "来代表特殊形式 ...

随机推荐

  1. Java开发笔记(五十三)关键字final的用法

    前面介绍了多态的相关用法,可以看到一个子类从父类继承之后,便能假借父类的名义到处晃悠.这种机制在正常情况之下没啥问题,但有时为了预防意外发生,往往只接受当事人来处理,不希望它的儿子乃至孙子来瞎掺和.可 ...

  2. 【转】Android播放音频MediaPlayer的几种方式介绍

    接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...

  3. Spring Boot 整合 elk

    一.elk 简介 Elasticsearch是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等. Logstas ...

  4. ueditor笔记

    一.ueditor是什么 UEditor 是由百度「FEX前端研发团队」开发的所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码. 二.ue ...

  5. 4 Redis 配置文件介绍

    2016-12-22 14:28:39 该系列文章链接NoSQL 数据库简介Redis的安装及及一些杂项基础知识Redis 的常用五大数据类型(key,string,hash,list,set,zse ...

  6. web前端图片上传

    图片上传有很多种形式,但是听说ios只能传字符串,所以为了安卓.ios和web能用一个接口上传图片,采用了基于base64 的方法上传图片. 下面是我的html <div class=" ...

  7. java程序员学C#

    因为工作需要,我要学习C#,其实我觉得不错,我喜欢了解更多的语言,因为这对我今后的发展很有帮助,毕竟技多不压身,下面是我今天学习后总结C#的基本语法: 我曾经学过C,而且又是java程序员,所以对我来 ...

  8. Dynamics 365新特性介绍:在视图中显示图片和提示

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复242或者20161230可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  9. 通过Web API调用Action时各种类型输入参数传递值的方法

    本人微信公众号:微软动态CRM专家罗勇 ,回复280或者20180906可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . Dy ...

  10. jquery获取内容和属性的方法

    通过jquery如何捕获文本内容和属性? text(),html(),val()及attr(). attr()更具有普遍性,元素text属性和表单value属性,可以通过attr()操作. <! ...