摘录 python核心编程

python的re模块允许多线程共享一个已编译的正则表达式对象,也支持命名子组。下表是常见的正则表达式属性:

函数/方法 描述
仅仅是re模块函数
compile(pattern,flags=0) 使用任何可选的标记来编译正则表达式的模式 ,然后返回一个正则表达式对象
re模块函数和正则表达式对象的方法
match(pattern,string,flags=0) 尝试使用带有可选标记的正则表达式的模式来匹配字符串,成功则返回匹配的对象,失败则返回None
search(pattern,string,flags=0) 使用可选标记搜索字符串中第一次出现的正则表达式模式,成功则返回匹配对象,失败则返回None
findall(pattern,string[,flags]) 查找字符串中所有(非重复)出现的正则表达式模式,返回一个匹配列表
finditer(pattern,string,[,flags]) 和findall()函数相同,但返回的是一个迭代器。对于每次匹配,迭代器都返回一个匹配对象
split(pattern,string,max=0) 根据正则表达式的模式分隔符,split函数将字符串分割为列表,然后返回成功匹配的列表,分割最多操作max次(默认分割所有匹配成功的位置)
re模块函数和正则表达式对象方法
sub(pattern,repl,string,count=0) 使用repl替换正则表达式模式在字符串中出现的位置,除非定义count,否则替换所有
purge() 清除隐式编译的正则表达式模式
常用的匹配对象方法
group(num=0) 返回整个匹配对象,或者编号为num的特定子组
groups(default=None) 返回一个包含所有匹配子组的元组(如果没有,则返回一个空元组)
groupdict(default=None) 返回一个包含所有匹配的命名子组的字典,所有子组名称作为字典的键(如没有,则返回一个空字典)
常用的模块属性
re.I、re.IGNORECASE 不区分大写的匹配
re.L、re.LOCALE 根据所使用的本地语言环通过\w\W\b\B\s\S实现匹配
re.M、re.MULTILINE ^和$分别匹配目标字符串中行的起始和结尾,而不是严格的匹配整个字符串本身的开始和结尾
re.S、re.DOTALL 点号.通常匹配除了换行符\n之外的所有单个字符,该标记表示点号能够匹配全部字符
re.X、re.VERBOSE 通过反斜线转义,否则所有空格加上#(以及在该行中所有后续问题)都被忽略,除非在一个字符类中或者允许注释并且提高可读性

compile()编译正则表达式

在模式匹配发生之前,正则表达式模式必须编译成正则表达式对象,而且正则表达式在执行的过程中可能进行多次的比较操作。所以,强烈建议使用compile函数进行预编译,用以提升程序的执行性能。其实所有的模块函数会对已编译的对象进行缓存。

匹配对象及其group()和groups()方法

处理正则表达式的时候,除了正则表达式对象外,还有一个叫做匹配对象的类型。成功调用match()和search()返回的对象就是匹配对象。

匹配对象有两个主要的方法:group()和groups()函数。二者的区别在于:前者可以返回整个匹配对象或者特定子组,后者仅返回包含全部子组的元组。

match()方法实现匹配字符串

match()方法视图从字符串的起始位置部分对模式进行匹配,成功则返回一个匹配对象,失败返回None,而匹配对象的group()方法能够显示成功的匹配:

>>> import re
>>> m = re.match('foo','foo')
>>> m
<_sre.SRE_Match object; span=(0, 3), match='foo'>
>>> if m is not None:
... m.group()
...
'foo'
>>> n = re.match('hello,foo!','foo')
>>> if n is not None:n.group()
...
>>> n

第二个例子中,由于foo并不是在开始的位置,所有没有成功。

search()在一个字符串中查找模式

search()的工作方式和match()完全一致,只是search()会用他的字符串参数,在任意位置对给定正则表达式模式搜索第一次出现的匹配情况。成功则返回匹配对象,否则返回None:

>>> n = re.match('foo','hello,foo!')
>>> if n is not None:ngroup()
...
>>>
>>> n = re.search('foo','hello,foo!')
>>> if n is not None:n.group()
...
'foo'

匹配多个字符

>>> bt = 'bat|bet|bit'
>>> m = re.match(bt,'bat')
>>> if m is not None:m.group()
...
'bat'
>>> m = re.match(bt,'blt')
>>> if m is not None:m.group()
...
>>> m = re.match(bt,'he bit me')
>>> if m is not None:m.group()
...
>>> m = re.search(bt,'he bit me')
>>> if m is not None:m.group()
...
'bit'

匹配任何单个字符

先看一个点号不能匹配换行符的示例:

>>> end = '.end'
>>> m = re.match(end,'bend')
>>> if m is not None:m.group()
...
'bend'
>>> m = re.match(end,'\nbend')
>>> if m is not None:m.group()
...
>>> m = re.search(end,'The end')
>>> if m is not None:m.group()
...
' end

再看一下搜索一个真正的句点的示例:

>>> patt314 = '3.14'
>>> pi_ptt = '3\.14'
>>> m = re.match(pi_ptt,'3.14')
>>> if m is not None:m.group()
...
'3.14'
>>> m = re.match(patt314,'')
>>> if m is not None:m.group()
...
''
>>> m = re.search(patt314,'3.14')
>>> if m is not None:m.group()
...
'3.14'
>>> m = re.match(pi_ptt,'3014')
>>> if m is not None:m.group()
...

上述例子又让我们强化认识了'3.14'和'3\.14'的区别。

创建字符集

下面的示例,用于展示[cr][23][dp][o2]和r2d2|c3po之间的区别:(会发现r2d2|c3po的限制将比[cr][23][dp][o2]更为严格)

>>> m = re.match('[cr][23][dp][o2]','c3po')
>>> if m is not None:m.group()
...
'c3po'
>>> m = re.match('[cr][23][dp][o2]','c2do')
>>> if m is not None:m.group()
...
'c2do'
>>> m = re.match('r2d2|c3po','c2do')
>>> if m is not None:m.group()
...
>>> m = re.match('r2d2|c3po','r2d2')
>>> if m is not None:m.group()
...
'r2d2'

重复、特殊字符以及分组

正则表达式最常见的情况包括:特殊字符的使用、正则表达式模式的重复出现、使用小括号对匹配模式的各部分进行分组和提取

我们可以使用正则表达式'\w+@\w+\.com'表示一个简单的邮件地址。当我们需要再域名前加上主机名,例如www.xxx.com,那就必须修改现有的正则表达式。同时,为了表示主机名是可选的,需要创建一个模式来匹配主机名,使用?操作符来表示该模式出现0或者一次: \w+@(\w+\.)?\w+\.com

>>> patt = '\w+@(\w+\.)?\w+\.com'
>>> re.match(patt,'somebody@xxx.com').group()
'somebody@xxx.com'
>>> re.match(patt,'somebody@www.xxx.com').group()
'somebody@www.xxx.com'
>>> re.match(patt,'somebody@xxx.yyy.zzz.com').group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'

针对上述例子的最后一句,下面进行扩展,允许任意数量的中间子域名存在:

>>> patt = '\w+@(\w+\.)*\w+\.com'
>>> re.match(patt,'somebody@xxx.yyy.zzz.com').group()
'somebody@xxx.yyy.zzz.com'

一般的,采用使用小括号来匹配和保存子组,以便于后续处理,而不是确定一个正则表达式匹配之后在一个单独的子程序里面手动编码来解析字符串:

>>> m = re.match('\w\w\w-\d\d\d','abc-123')
>>> if m is not None:m.group()
...
'abc-123'
>>> m = re.match('\w\w\w-\d\d\d','abc-xyz')
>>> if m is not None:m.group()
...

扩展,修改上述正则表达式,使该正则表达式能够提取字母数字字符串和数字:

>>> m = re.match('(\w\w\w)-(\d\d\d)','abc-123')
>>> m.group()
'abc-123'
>>> m.group(1)
'abc'
>>> m.group(2)
''
>>> m.groups()
('abc', '')

下面的例子展示了不同的分组排列,以及group()和groups()函数的执行情况:

>>> m = re.match('ab','ab')
>>> m.group()
'ab'
>>> m.groups()
()
>>> m = re.match('(ab)','ab')
>>> m.group()
'ab'
>>> m.group(1)
'ab'
>>> m.group(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: no such group
>>> m.groups()
('ab',)
>>> m = re.match('(a)(b)','ab')
>>> m.group()
'ab'
>>> m.group(1)
'a'
>>> m.group(2)
'b'
>>> m.groups()
('a', 'b')
>>> m = re.match('(a(b))','ab')
>>> m.group()
'ab'
>>> m.group(1)
'ab'
>>> m.group(2)
'b'
>>> m.groups()
('ab', 'b')

匹配字符串的起始和结尾以及单词边界

下面例子展示了表示位置的正则表达式操作符。更多的用于表示搜索而不是匹配,因为match()总是从字符串开始位置进行匹配:

>>> import re
>>> m = re.search('^The','The end')
>>> if m is not None:
... m.group()
...
'The'
>>> m = re.search('^The','end The')
>>> if m is not None:
... m.group()
...
>>> m = re.search(r'\bthe','bite the dog')
>>> if m is not None:
... m.group()
...
'the'
>>> m = re.search(r'the','bite the dog')
>>> if m is not None:
... m.group()
...
'the'
>>> m = re.search(r'the','bitethe dog')
>>> if m is not None:
... m.group()
...
'the'
>>> m = re.search(r'\Bthe','bite the dog')
>>> if m is not None:
... m.group()
...

使用findall()和finditer()查找每一次出现的位置

findall()查询字符串中某个正则表达式模式全部的非重复出现情况。于search()执行的搜索字符串类似,但是不同之处在于:findall()总是返回一个列表,列表按顺序包含所有成功匹配的部分:

>>> re.findall('car','carry the barcardi to the car')
['car', 'car', 'car']

finditer()于findall类似,但是返回的是一个迭代器,使得更节省内存。(对于迭代器,可以使用迭代器相关的知识提取内容)

使用sub()和subn()搜索和替换

两者的作用基本一致,都是将某个字符串中所有匹配正则表达式的部分进行某种形式的替换,相比于sub(),subn()还返回一个表示替换的总数,替换后的字符串和表示替换总数的数字一起作为一个拥有两个元素的元组返回:

>>> re.subn('X','Mr.Smith','attn:X\n\nDear X,\n')
('attn:Mr.Smith\n\nDear Mr.Smith,\n', 2)
>>> print(re.sub('X','Mr.Smith','attn:X\n\nDear X,\n'))
attn:Mr.Smith Dear Mr.Smith,

在限定模式上使用split()分割字符串

先来一个普通的字符串分割:

>>> re.split(':','str1:str2:str3')
['str1', 'str2', 'str3']

再来见识一下巨大威力的分割效果:例如用于web站点的简单解析器,这是普通的字符串分割没有的强大的处理方式

>>> DATA = (
... 'Moutain view, CA 94040',
... 'Sunny, CA',
... 'Los Altos, 94023',
... 'Cuper 95014',
... 'Palo Alto CA',
... )
>>> for i in DATA:
... print(re.split(', |(?= (?:\d{5}|[A-Z]{2})) ',i))
...
['Moutain view', 'CA', '']
['Sunny', 'CA']
['Los Altos', '']
['Cuper', '']
['Palo Alto', 'CA']

上述例子中的正则表达式使用了一个组件:使用split语句基于逗号分割字符串,或者如果空格紧跟在五个数字或者两个大写字母之后,就用split语句分割该空格。而这种分割效果很难用str.split()达到。

这里涉及到的正则表达式的扩展符号的使用,足够让我们另写一篇文章介绍了。

python 正则表达式re使用模块(match()、search()和compile())的更多相关文章

  1. python正则表达式之re模块方法介绍

    python正则表达式之re模块其他方法 1:search(pattern,string,flags=0) 在一个字符串中查找匹配 2:findall(pattern,string,flags=0) ...

  2. Python正则表达式与re模块介绍

    Python中通过re模块实现了正则表达式的功能.re模块提供了一些根据正则表达式进行查找.替换.分隔字符串的函数.本文主要介绍正则表达式先关内容以及re模块中常用的函数和函数常用场景. 正则表达式基 ...

  3. python 正则表达式 (重点) re模块

    京东的注册页面,打开页面我们就看到这些要求输入个人信息的提示.假如我们随意的在手机号码这一栏输入一个11111111111,它会提示我们格式有误.这个功能是怎么实现的呢?假如现在你用python写一段 ...

  4. Python正则表达式与hashlib模块

    菜鸟学python第十六天 1.re模块(正则表达式) 什么是正则表达式 正则表达式是一个由特殊字符组成的序列,他能帮助对字符串的某种对应模式进行查找. 在python中,re 模块使其拥有全部的正则 ...

  5. python正则表达式与re模块-02

    正则表达式 正则表达式与python的关系 # 正则表达式不是Python独有的,它是一门独立的技术,所有的编程语言都可以使用正则 # 但要在python中使用正则表达式,就必须依赖于python内置 ...

  6. Python正则表达式与re模块

    在线正则表达式测试 http://tool.oschina.net/regex/ 常见匹配模式 模式 描述 \w 匹配字母数字及下划线 \W 匹配非字母数字下划线 \s 匹配任意空白字符,等价于 [\ ...

  7. python 正则表达式与re模块

    一.正则表达式 用途 用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. #### 简单地说 就是用于字符串匹配的 字符组 在 ...

  8. [ python ] 正则表达式及re模块

    正则表达式 正则表达式描述: 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个‘规则字符串’,这个‘规则字符串’用来    表达对字符串的一种过滤 ...

  9. python正则表达式之re模块使用

    python第一个正则表达式 https://www.imooc.com/learn/550 r'imooc'  Pattern Match result In [2]: import re In [ ...

随机推荐

  1. 【CPLUSOJ】【动态规划】最短回文串

    题目链接 [问题描述] 如果一个字符串正过来读和倒过来读是一样的,那么这个字符串就被称作回文串.例如abcdcba,abcddbca就是回文串,而abcdabcd不是. 你要解决的问题是:对于任意一个 ...

  2. python网络爬虫之自动化测试工具selenium[二]

    目录 前言 一.获取今日头条的评论信息(request请求获取json) 1.分析数据 2.获取数据 二.获取今日头条的评论信息(selenium请求获取) 1.分析数据 2.获取数据 房源案例(仅供 ...

  3. Linux常见的Shell命令

    1.具体的shell命令用法可以通过help或man命令进入手册来查询其具体的用法.2.终端本质上对应着linux上的/dev/tty设备,linux的多用户登录就是通过不同的/dev/tty设备完成 ...

  4. flanneld 安装

    目录 flanneld 安装 下载分发flanneld二进制文件 分发二进制文件到所有集群的节点 创建Flannel证书和私钥 创建证书签名请求 生成证书和私钥 向etcd写入Pod网段信息 创建fl ...

  5. Ansible 常见模块介绍

    目录 Ansible 常见模块介绍 ping 模块 command 模块 cron 模块 user 模块 group 模块 copy 模块 file 模块 service 模块 shell 模块 sc ...

  6. re实战记录

    re实战记录 针对网页中的空格符 一般使用的.,但是它不能匹配\n,所以使用[\s\S]或者[\d\D]匹配所有字符 import re l1=r''' <div class="thu ...

  7. 文件和目录权限chmod、更改所有者和所属组chown、umask、隐藏权限lsattr/chattr 使用介绍

    第2周第3次课(3月28日) 课程内容:2.14 文件和目录权限chmod2.15 更改所有者和所属组chown2.16 umask2.17 隐藏权限lsattr/chattr 2.14 文件和目录权 ...

  8. 【网络流相关】最大流的Dinic算法实现

    Luogu P3376 于\(EK\)算法求最大流时每一次只求一条增广路,时间复杂度会比较高.尽管实际应用中表现比较优秀,但是有一些题目还是无法通过. 那么我们就会使用\(Dinic\)算法实现多路增 ...

  9. JavaScript新手经常遇到的问题(二)

    1.Form表单只提交数据而不进行页面跳转的方法 <script type="text/javascript" src="js/jquery/jquery-1.8. ...

  10. 全面认识 RUST -- 掌控未来的雷电

    文章目录 RUST 简介 如何衡量语言的好坏? 静态语言 编译器 语言定位 代表性项目 Hello World RUST 前景 RUST 简介 Rust 是一种兼顾内存安全.高并发和稳定运行的编程语言 ...