python 正则表达式re使用模块(match()、search()和compile())
摘录 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())的更多相关文章
- python正则表达式之re模块方法介绍
python正则表达式之re模块其他方法 1:search(pattern,string,flags=0) 在一个字符串中查找匹配 2:findall(pattern,string,flags=0) ...
- Python正则表达式与re模块介绍
Python中通过re模块实现了正则表达式的功能.re模块提供了一些根据正则表达式进行查找.替换.分隔字符串的函数.本文主要介绍正则表达式先关内容以及re模块中常用的函数和函数常用场景. 正则表达式基 ...
- python 正则表达式 (重点) re模块
京东的注册页面,打开页面我们就看到这些要求输入个人信息的提示.假如我们随意的在手机号码这一栏输入一个11111111111,它会提示我们格式有误.这个功能是怎么实现的呢?假如现在你用python写一段 ...
- Python正则表达式与hashlib模块
菜鸟学python第十六天 1.re模块(正则表达式) 什么是正则表达式 正则表达式是一个由特殊字符组成的序列,他能帮助对字符串的某种对应模式进行查找. 在python中,re 模块使其拥有全部的正则 ...
- python正则表达式与re模块-02
正则表达式 正则表达式与python的关系 # 正则表达式不是Python独有的,它是一门独立的技术,所有的编程语言都可以使用正则 # 但要在python中使用正则表达式,就必须依赖于python内置 ...
- Python正则表达式与re模块
在线正则表达式测试 http://tool.oschina.net/regex/ 常见匹配模式 模式 描述 \w 匹配字母数字及下划线 \W 匹配非字母数字下划线 \s 匹配任意空白字符,等价于 [\ ...
- python 正则表达式与re模块
一.正则表达式 用途 用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. #### 简单地说 就是用于字符串匹配的 字符组 在 ...
- [ python ] 正则表达式及re模块
正则表达式 正则表达式描述: 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个‘规则字符串’,这个‘规则字符串’用来 表达对字符串的一种过滤 ...
- python正则表达式之re模块使用
python第一个正则表达式 https://www.imooc.com/learn/550 r'imooc' Pattern Match result In [2]: import re In [ ...
随机推荐
- [题解]洛谷P1094——纪念品分组
原题链接: https://www.luogu.org/problem/P1094 题目简述: 有NNN件纪念品,每个纪念品都有特定的价格,要求将他们分组,每组纪念品之和不得超过MMM,并且每组最多只 ...
- 2019年12月1日Linux开发手记
配置ubuntu摄像头: 1.设置→添加→usb控制器→兼容usb3.0 2.虚拟机→可移动设备→web camera→连接(断开主机) 3.查看是否配置成功,打开终端,输入: susb ls /de ...
- BeautifulSoup模块的常用方法小结
Beautiful Soup库是解析.遍历.维护“标签树”的功能库. url = "http://desk.zol.com.cn/" request = requests.get( ...
- JSONPath小试牛刀之Snack3
最近在网上看了些JSONPath的入门例子.打算用Snack3这个框架写写例子.json path对`JSON的处理绝对是神器. 1.准备JSON字符串 { "store": { ...
- Django如何启动源码分析
Django如何启动源码分析 启动 我们启动Django是通过python manage.py runsever的命令 解决 这句话就是执行manage.py文件,并在命令行发送一个runsever字 ...
- 使用 Flask 和 Vue.js 来构建全栈单页应用
在这个教程中,我将向你展示如何将 Vue 的单页面应用和 Flask 后端连接起来. 简单的来说,如果想在 Flask 中使用 Vue 框架是没有什么问题的. 但在实际中存在一个明显的问题就是 Fla ...
- OC中内存管理(转)
OC内存管理 一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继 ...
- 发送json给服务器
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 1.URL NSURL *url = [NSURL URLW ...
- java多线程与线程池
1. 场景描述 以前多线程也常用,这次因需再页面上用到多线程,如下图,总结下,有需要的朋友可以参考下. 2. 解决方案 2.1 线程池概念 线程池官方定义不说了,通俗说下:池子的概念,事先(预定义)创 ...
- NAT的三种类型
一.静态NAT 内部本地地址一对一转换成内部全局地址,相当内部本地的每一台PC都绑定了一个全局地址,即使这个地址没有被使用,其他的电脑也不能拿来转换使用,这样容易造成IP地址的资源浪费,一般是用于在内 ...