摘录 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. Linux下使用Nginx做CDN服务器下的配置

    由于使用docker配置Nginx比较方便,所以博主就使用docker做为容器配置下 第一步.配置docker-compose.yml文件 version: services: nginx: rest ...

  2. javaScript——label语句

    第一次看见label语句是这样一个场景: function foo() {x: 1} 当时十分疑惑,为什么不报错呢?对象可以这样写? 后来知道这个是label语句,一般配合break和continue ...

  3. 痞子衡嵌入式:恩智浦机器视觉模块OpenMV-RT那些事(1)- 初体验

    大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是机器视觉模块OpenMV-RT初体验. 近些年机器视觉应用一直是个很火的方向,想象一下机器如果能长上"眼睛",是不 ...

  4. Scala函数式编程(四)函数式的数据结构 上

    这次来说说函数式的数据结构是什么样子的,本章会先用一个list来举例子说明,最后给出一个Tree数据结构的练习,放在公众号里面,练习里面给出了基本的结构,但代码是空缺的需要补上,此外还有预留的test ...

  5. P1035 级数求和

    题目描述 已知:S_n= 1+1/2+1/3+…+1/nSn​=1+1/2+1/3+…+1/n.显然对于任意一个整数KK,当nn足够大的时候,S_nSn​大于KK. 现给出一个整数KK(1 \le k ...

  6. Qt的安装

    由于之前用的vs2017是集成c++环境的,加之dev c++ 编码管理起来不是很方便,Mytc (win10不支持) ,所以转而向Qt 开发工具,以下是大概安装过程 下载地址 清华源:https:/ ...

  7. 普通用户修改时间 sudo

    sudo date neokylinV7.0  desktop 1.给/etc/sudoers加权限 # chmod u+w /etc/sudoers 2.添加配置 # vim /etc/sudoer ...

  8. python 备忘录

    1. python 变量 区分大小写 2. 字符串可以用   'X'  "X"  '''X'''  """X""" 3. ...

  9. PHP计算两组经纬度坐标之间的距离

    定义π define('PI',3.1415926535898); define('EARTH_RADIUS',6378.137); 计算两组经纬度坐标 之间的距离 /** * 计算两组经纬度坐标 之 ...

  10. 一道时间复杂度为O(N)空间复杂度为O(1)的排序问题

    题目:对1, 2, ... , n的一个无序数组,排序,要求时间复杂度为O(N),空间复杂度为O(1). 思路:该题利用数组元素和数组下标相差1的关系,Java代码如下: import java.ut ...