Python 正则表达式
在开始之前我们先要明白两个问题。
1、什么是正则表达式?
2、为什么要学习正则表达式?
人类在做一件事之前,总是会先问一下为什么要这么做『你可能说你没有这么想过,我想说的是其实你下意识已经考虑过了』。其实问为什么的时候,既是给我们做这件事的原因,也是我们遇到困难时坚持下去的动力。
那么我们先来看下我们今天的这两个问题。
什么是正则表达式?
维基百科上的解释如下:
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE),又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。
我的理解是,正则表达式是一种用于对比已有字符串是否符合我们特定顺序格式的特殊字符串。用于检索一段字符串是否包含所需字符内容的特定用途。
为什么要学习正则表达式?
要回答这个问题先要搞明白正则表达式可以解决什么问题。事实上正则表达式可用于解决一下问题:
- 搜索文件中的固定字符串。
- 检索网页上的 URL 连接、电子有限地址等等。
- 对文件中的字符串进行替换等操作。
- 搜索文件夹中包含固定字符串的文件。
- 索索文件中固定位置的的固定字符串。
从以上正则表达式解决的问题,我们可以通过正则表达式来实现编辑器中的查找与替换功能、文件浏览器的文件搜索功能、网络爬虫等等,总结一下正则表达式的应用场景有两个一是搜索、二是替换。
Python 是用来实现网络爬虫最好的编程语言,因此学习正则表达式即为了在网络爬虫中能够更好的处理获取到的数据。
Python 提供了专门用于处理正则表达式的模块——re 模块,它提供了与 Perl 语言类似的正则表达式匹配操作。接下来我们一块来看一下如何使用 re 模块来实现搜索和替换。
re 模块实现字符串的搜索
字符串的搜索,可以用来搜索文件中符合特定规则的字符数据,比如搜索网页中电话号码、邮箱等。通过 re 模块可以快速的将所需要的数据提取出来。
接下来的内容我们一起来看下如何将一段文本中的邮箱地址搜索并提取出来。文本内容如下:
Send personal email to keinye@foxmail.com or keinye.dev@gmail.com. For questens about Python use <keinye@foxmail.kein.com>. If you message is urgent try keinye.dev@keinye.gmail.com.
现在我们要从上面的文本中提取出所有的 email 地址。
# -*- coding:utf-8 -*-
import re
text = '''
Send personal email to keinye@foxmail.com or keinye.dev@gmail.com.
For questens about Python use <keinye@foxmail.kein.com>.
If you message is urgent try keinye.dev@keinye.gmail.com.
'''
prog = re.compile("\w+(\.\w+)*@\w+(\.\w+)+")
print "******** re search ********"
print re.search(prog, text).group()
print "******** re findall ********"
print re.findall("\w+(?:\.\w+)*@\w+(?:\.\w+)+", text)
print "******** re finditer ********"
for n in re.finditer("\w+(?:\.\w+)*@\w+(?:\.\w+)+", text):
print n.group()
print n.span()
运行以上代码,我们可以得到以下结果
******** re search ********
keinye@foxmail.com
******** re findall ********
['keinye@foxmail.com', 'keinye.dev@gmail.com', 'keinye@foxmail.kein.com', 'keinye.dev@keinye.gmail.com']
******** re finditer ********
keinye@foxmail.com
(24, 42)
keinye.dev@gmail.com
(46, 66)
keinye@foxmail.kein.com
(99, 122)
keinye.dev@keinye.gmail.com
(154, 181)
在以上代码中我们分别通过 search、findall 和 finditer 三个方法来提取文本中的 email。从结果上来看使用同一个整个表达式 search 方法仅仅是获取到了第一个文本中出现的第一个 email。findall 和 finditer 提取出来文本中所有的 email,而且通过 finditer 我们还能够得到 email 在文本中的位置。
通过以上代码的执行结果,我们可以看出者三个方法的适用场景有所不同
- search 方法适用于确定一段文本中是否包含有符合正则表达式的字符串『只关心是否有,而不关心数量』,比如搜索网页中是否包含某一关键字。
- findall 适用于将文本中所有符合正则表达式的字符串提取出来,比如获取联系电话、地址等等。
- finditer 适用于获取文本中符合正则表达式的字符串的位置,比如修改,删除等等操作。
re 模块实现字符串的替换
字符串的替换是另外一个重要的功能,在 python 中我们可以通过 strip()、replace() 和 re.sub() 来实现字符串的替换,本节主要对 re.sub() 函数进行介绍。
re.sub() 函数的定义如下
re.sub(pattern, repl, string, count=0, flags=0)
各个参数的含义如下:
- pattern:表示正则表达式中的模式字符串;
- repl:用来替换匹配内容的字符串(既可以是字符串,也可以是函数);
- string:要被处理的,要被替换的字符串;
- count:可选参数,要替换的最大次数,如果忽略或设置为0,所有的匹配都会被替换;
- flags:可选标记,可以通过指定值来影响正则表达式的行为。
以下是使用示例
# -*- coding:utf-8 -*-
import re
text = '''
Send personal email to keinye@foxmail.com or keinye.dev@gmail.com.
For questens about Python use <keinye@foxmail.kein.com>.
If you message is urgent try keinye.dev@keinye.gmail.com.
'''
prog = re.compile("\w+(\.\w+)*@\w+(\.\w+)+")
print '******** re.sub count=3********'
replace_text = re.sub(prog, 'keinYe', text, count=3)
print replace_text
print '******** re.sub count=0********'
replace_text = re.sub(prog, 'keinYe', text, count=0)
print replace_text
print '******** re.sub count is None********'
replace_text = re.sub(prog, 'keinYe', text)
print replace_text
执行结果如下:
Send personal email to keinYe or keinYe.
For questens about Python use <keinYe>.
If you message is urgent try keinye.dev@keinye.gmail.com.
******** re.sub count=0********
Send personal email to keinYe or keinYe.
For questens about Python use <keinYe>.
If you message is urgent try keinYe.
******** re.sub count is None********
Send personal email to keinYe or keinYe.
For questens about Python use <keinYe>.
If you message is urgent try keinYe.
推荐两个学习正则表达式的书