Python3 如何优雅地使用正则表达式(详解二)
使用正则表达式
现在我们开始来写一些简单的正则表达式吧。Python 通过 re 模块为正则表达式引擎提供一个接口,同时允许你将正则表达式编译成模式对象,并用它们来进行匹配。
小甲鱼解释:re 模块是使用 C 语言编写,所以效率比你用普通的字符串方法要高得多;将正则表达式进行编译(compile)也是为了进一步提高效率;后边我们会经常提到“模式”,指的就是正则表达式被编译成的模式对象。
编译正则表达式
正则表达式被编译为模式对象,该对象拥有各种方法供你操作字符串,如查找模式匹配或者执行字符串替换。
- >>> import re
- >>> p = re.compile('ab*')
- >>> p
- <_sre.SRE_Pattern object at 0x...>
复制代码
re.compile() 也可以接受 flags 参数,用于开启各种特殊功能和语法变化,我们会在后边一一介绍。
现在我们先来看个简单的例子:
- >>> p = re.compile('ab*', re.IGNORECASE)
复制代码
正则表达式作为一个字符串参数传给 re.compile()。由于正则表达式并不是 Python 的核心部分,因此没有为它提供特殊的语法支持,所以正则表达式只能以字符串的形式表示。(有些应用根本就不需要使用到正则表达式,所以 Python 社区的小伙伴们认为没有必要将其纳入 Python 的核心。)相反,re 模块仅仅是作为 C 的扩展模块包含在 Python 中,就像 socket 模块和 zlib 模块。
使用字符串来表示正则表达式保持了 Python 简洁的一贯风格,但也因此有一些负面影响,下边我们就来谈一谈。
麻烦的反斜杠
上一篇中我们已经提到了,正则表达式使用 '\' 字符来使得一些普通的字符拥有特殊的能力(例如 \d 表示匹配任何十进制数字),或者剥夺一些特殊字符的能力(例如 \[ 表示匹配左方括号 '[')。这会跟 Python 字符串中实现相同功能的字符发生冲突。
小甲鱼解释:挺拗口,接着看例子你就懂了~
现在的情况是,你需要在 LaTeX 文件中使用正则表达式匹配字符串 '\section'。因为反斜杠作为需要匹配的特殊字符,所以你需要再它前边加多一个反斜杠来剥夺它的特殊功能。所以我们会把正则表达式的字符写成 '\\section'。
但不要忘了,Python 在字符串中同样使用反斜杠来表示特殊意义。因此,如果我们想将 '\\section' 完整地传给 re.compile(),我们需要再次添加两个反斜杠......
| 匹配字符 | 匹配阶段 |
| \section | 需要匹配的字符串 |
| \\section | 正则表达式使用 '\\' 表示匹配字符 '\' |
| "\\\\section" | 不巧,Python 字符串也使用 '\\' 表示字符 '\' |
简而言之,为了匹配反斜杠这个字符,我们需要在字符串中使用四个反斜杠才行。所以,在正则表达式中频繁地使用反斜杠,会造成反斜杠风暴,进而导致你的字符串极其难懂。
解决方法是使用 Python 的原始字符串来表示正则表达式(就是在字符串前边加上 r,大家还记得吧...):
| 正则字符串 | 原始字符串 |
| "ab*" | r"ab*" |
| "\\\\section" | r"\\section" |
| "\\w+\\s+\\1" | r"\w+\s+\1" |
小甲鱼解释:强烈建议使用原始字符串来表达正则表达式。
实现匹配
当你将正则表达式编译之后,你就得到一个模式对象。那你拿他可以用来做什么呢?模式对象拥有很多方法和属性,我们下边列举最重要的几个来讲:
| 方法 | 功能 |
| match() | 判断一个正则表达式是否从开始处匹配一个字符串 |
| search() | 遍历字符串,找到正则表达式匹配的第一个位置 |
| findall() | 遍历字符串,找到正则表达式匹配的所有位置,并以列表的形式返回 |
| finditer() | 遍历字符串,找到正则表达式匹配的所有位置,并以迭代器的形式返回 |
如果没有找到任何匹配的话,match() 和 search() 会返回 None;如果匹配成功,则会返回一个匹配对象(match object),包含所有匹配的信息:例如从哪儿开始,到哪儿结束,匹配的子字符串等等。
接下来我们一步步讲解:
- >>> import re
- >>> p = re.compile('[a-z]+')
- >>> p
- re.compile('[a-z]+')
复制代码
现在,你可以尝试使用正则表达式 [a-z]+ 去匹配各种字符串。
例如:
- >>> p.match("")
- >>> print(p.match(""))
- None
复制代码
因为 + 表示匹配一次或者多次,所以空字符串不能被匹配。因此,match() 返回 None。
我们再尝试一个可以匹配的字符串:
- >>> m = p.match('fishc')
- >>> m
- <_sre.SRE_Match object; span=(0, 5), match='fishc'>
复制代码
在这个例子中,match() 返回一个匹配对象,我们将其存放在变量 m 中,以便日后使用。
接下来让我们来看看匹配对象里边有哪些信息吧。匹配对象包含了很多方法和属性,以下几个是最重要的:
| 方法 | 功能 |
| group() | 返回匹配的字符串 |
| start() | 返回匹配的开始位置 |
| end() | 返回匹配的结束位置 |
| span() | 返回一个元组表示匹配位置(开始,结束) |
大家看:
- >>> m.group()
- 'fishc'
- >>> m.start()
- 0
- >>> m.end()
- 5
- >>> m.span()
- (0, 5)
复制代码
由于 match() 只检查正则表达式是否在字符串的起始位置匹配,所以 start() 总是返回 0。
然而,search() 方法可就不一样咯:
- >>> print(p.match('^_^fishc'))
- None
- >>> m = p.search('^_^fishc')
- >>> print(m)
- <_sre.SRE_Match object; span=(3, 8), match='fishc'>
- >>> m.group()
- 'fishc'
- >>> m.span()
- (3, 8)
复制代码
在实际应用中,最常用的方式是将匹配对象存放在一个局部变量中,并检查其返回值是否为 None。
形式通常如下:
- p = re.compile( ... )
- m = p.match( 'string goes here' )
- if m:
- print('Match found: ', m.group())
- else:
- print('No match')
复制代码
有两个方法可以返回所有的匹配结果,一个是 findall(),另一个是 finditer()。
findall() 返回的是一个列表:
- >>> p = re.compile('\d+')
- >>> p.findall('3只小甲鱼,15条腿,多出的3条在哪里?')
- ['3', '15', '3']
复制代码
findall() 需要在返回前先创建一个列表,而 finditer() 则是将匹配对象作为一个迭代器返回:
- >>> iterator = p.finditer('3只小甲鱼,15条腿,还有3条去了哪里?')
- >>> iterator
- <callable_iterator object at 0x10511b588>
- >>> for match in iterator:
- print(match.span())
- (0, 1)
- (6, 8)
- (13, 14)
复制代码
小甲鱼解释:如果列表很大,那么返回迭代器的效率要高很多。迭代器的相关知识请看:《零基础入门学习Python》048 | 魔法方法:迭代器
Python3 如何优雅地使用正则表达式(详解二)的更多相关文章
- JavaScript正则表达式详解(一)正则表达式入门
JavaScript正则表达式是很多JavaScript开发人员比较头疼的事情,也很多人不愿意学习,只是必要的时候上网查一下就可以啦~本文中详细的把JavaScript正则表达式的用法进行了列表,希望 ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
- Java 正则表达式详解_正则表达式
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- Django url配置 正则表达式详解 分组命名匹配 命名URL 别名 和URL反向解析 命名空间模式
Django基础二之URL路由系统 本节目录 一 URL配置 二 正则表达式详解 三 分组命名匹配 四 命名URL(别名)和URL反向解析 五 命名空间模式 一 URL配置 Django 1.11版本 ...
- 【python3+request】python3+requests接口自动化测试框架实例详解教程
转自:https://my.oschina.net/u/3041656/blog/820023 [python3+request]python3+requests接口自动化测试框架实例详解教程 前段时 ...
- (转)Python3.5——装饰器及应用详解
原文:https://blog.csdn.net/loveliuzz/article/details/77853346 Python3.5——装饰器及应用详解(下)----https://blog.c ...
- (转)linux正则表达式详解
linux正则表达式详解 http://blog.csdn.net/wuliowen/article/details/64131815 1:什么是正则表达式: 简单的说,正则表达式就是处理字符串的方法 ...
- Python3、setuptools、Pip3安装详解
Python3.setuptools.Pip3安装详解 2017年08月19日 18:58:47 安静的技术控 阅读数:26002 版权声明:本文为博主原创文章,未经博主允许不得转载. http ...
- Linux文本处理三剑客之grep及正则表达式详解
Linux文本处理三剑客之grep及正则表达式详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Linux文本处理三剑客概述 grep: 全称:"Global se ...
- Django路由配置之正则表达式详解
正则表达式详解 urls.py from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles ...
随机推荐
- 实Schur分解
前面已经说过LU,Cholesky和QR分解,这次介绍的是实Schur分解.对这个分解的定义是任意一个矩阵A,可有如下形式的分解: U*A*U' = B;其中B是拟 ...
- CentOS卸载openoffice
rpm -e `rpm -qa |grep openoffice` `rpm -qa |grep ooobasis` 这样算是比较彻底的
- springMVC+ mongdb + redis +Jedis 环境搭建
环境信息: JDK1.7 : Eclipse 4.4.1 ; mongdb + mongVUE:mongDB的安装 redis的下载和安装:window下安装redis maven3.0.5 新建ma ...
- java入门之异常处理小结
(1)异常和错误 异常(Exception):不正常的事件,会中断程序,在运行中发生的意外,程序本身可以处理,防止程序中断:程序中会捕获的异常信息,并告诫用程序员,不要求程序必须对它做处理.catch ...
- POJ1505:Copying Books(区间DP)
Description Before the invention of book-printing, it was very hard to make a copy of a book. All th ...
- MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)
MySQL主从复制(Master-Slave)即同步与读写分离(MySQL-Proxy)即集群
- Android开发系列之button事件的4种写法
经过前两篇blog的铺垫,我们今天热身一下,做个简单的样例. 文件夹结构还是引用上篇blog的截图. 详细实现代码: public class MainActivity extends Activit ...
- VS中批量删除cs代码中的#region和#endregion
Visual Studio中如何批量删除cs代码中的#region和#endregion,不删除它们中间的代码,只删除这两个标记及标记的注解的方法.Vs中提供了很强大的文本查找与替换功能,简单的替换只 ...
- Eclipse中Java文件图标由实心J变成空心J的问题
在eclipse中空心J的java文件,表示不被包含在项目中进行编译,而是当做资源存在项目中.例如 当是单个文件为空心J的时候 1.右击该文件 -- >BuildPath -->Inclu ...
- ios 中如何应对UIScrollView快速滑动(暴力用户,暴力测试)
1.实现UIScrollViewDelegate 开始滑动: - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView 滑动 ...