正则表达式

正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。本文简单讲述了re模块的六大匹配方法和一些匹配模式。

[TOC]

导入

import re

语法

有一点要注意Python的字符串本身也用’\’转义,所以要特别注意,一般我们都建议使用Python的r前缀,就不用考虑转义的问题了。

匹配位置的元字符

符号 符号 在正则中的含义
^ 脱字符 匹配一行开头的字符
$ 美元符 匹配一行结束的位置
\b 单词分界 匹配单词的边界

匹配单个字符的元字符

符号 符号 在正则中的含义
. 点号 匹配单个任意字符
[…] 字符组 匹配里面列出来的字符
[^…] 排除字符组 匹配非其中列出的字符

提供计数功能的元字符

符号 符号 在正则中的含义
? 问号 可以匹配一次,但不必须匹配
* 星号 可以匹配任意次,但不必须匹配
+ 加号 至少匹配一次,最多可以匹配任意次
{min,max} 区间 至少匹配min次,最多可匹配max次

模式

更加详尽的模式请参考附录

匹配行的开头

先说一个简单的例子:匹配以cat开头的

patt=re.compile(r'^cat')

表示匹配以c作为一行的第一个字符,后面跟着a,后面跟着t
所以’vocative’就不会被匹配到,原因是因为cat在字符的里面

匹配行的结尾

如何我们要是以某一个字符串结尾的,比如我们要查邮件是以
BR或者Bestregards结尾的,如何匹配:我们用美元符号$来处理

import re
sentence='''Hi Jack:\n
Python is a beautiful language\n
BR'''
patt=re.compile(r'(BR|Bestregards)$')
m=re.search(patt,sentence)
if m :
print ('match')
else:
print ('not match')
>>>
match

匹配单词的边界

前面介绍了匹配行的开头和结尾,那么如何匹配单词的边界呢,正则里面有2个特殊字符\b and \B来匹配单词的边界 :
\b 匹配的模式是一个单词的边界(不论这个单词的前面是有字符还是没有字符)
\B 匹配出现在一个单词中间的模式
例如:

the            #匹配包含有'the'的字符串
\bthe #匹配任何以'the'开始的字符串
\bthe\b #仅仅匹配单词'the'
\Bthe #匹配任意包含'the'但不以'the'开头的单词

匹配字符组

比如我们需要匹配’grey’或者’gray’的时候,怎么办,可以用正则的[]来表示,gr[ea]y,表示先找到g,然后找到r,然后找到e或者a,最后是一个y

import re
word='grey'
patt=re.compile(r'gr[ea]y')
m=re.match(patt,word)
if m :
print ('match')
else:
print ('not match')
>>>
match

匹配中的多选模式

我们可以用’|’来匹配任意子表达式,‘|’是一个非常简便的元字符,它的意思是”或”,通过它我们能把不同的子表达式组合成一个总的表达式,比如’am’|’pm’就是能够同时匹配其中任意一个的正则表达式,回头再看上面的例子’gr[ea]y’,其实能写成’grey|gray’,或者’gr(e|a)y’

匹配中的可选匹配(非必需匹配)

比如6月4号,这个6月可能写成’June’也可以写成’Jun’,而且日期也有可能写作’fourth’或者’4th’或者4,我们可以写成(June|Jun)(fourth|4th|4),但是有没有其他办法呢,可以用问号?表示可选项
我们分步来处理:
第一部分:(June|Jun)改为(June?),什么意思呢
意思是说’?’出现在一个e后面,表示e是可选的
第二部分:(fourth|4th|4)改为(fourth|4(th)?),什么意思呢
意思是说’?’出现在一个括号后面,表示这个括号内的内容是可选的

最后这个复杂的(June|Jun)(fourth|4th|4)就可以变成了June?(fourth|4(th)?)

匹配重复出现的字符

重复出现用+和*表示,但是二者有一些小的区别

  • 加号(+)表示:前面紧邻的元素出现一次或者多次,也就是至少出现一次
  • 星号(*)表示:前面紧邻的元素出现任意多次,或者不出现.

即:
a*表示0个或者多个a,所以为0的时候,就是空字符
a+表示1个或者多个a,所以a至少要有1次

匹配重复出现n次的内容

  • 比如我们想匹配前面的内容重复出现的次数,比如3次,或者是一个区间,比如1-3次,如何匹配:

    import re
    num_str='123aa45'
    patt=re.compile(r'([1-9]{3})')
    m=re.match(patt,num_str)
    if m:
    print (m.group())
    >>>
    123
  • 为重复匹配次数设定一个区间

比如美国股票的代码,都是字符有大写的也有小写,基本都是在1到5个字母,如何用正则表达呢? [a-zA-Z]{1,5},就可以来匹配美国股票代码(1到5个字母)

匹配中去除不想匹配的字符

比如我们想匹配除了1到6以外的任何字符串,怎么办,简单用[^1-6],这个字符组中开头的^表示”排除的意思”.有同学会说,你刚才不是说^表示开头吗,怎么现在变成排除型了?

下面就是我要解释的,正则的复杂性:

  • 当^在字符组的外面的时候”表示一个行的开头”
  • 当^在字符组的内部(而且是必须紧接着字符组的第一个方括号之后),它就是一个元字符,表示排除型

例子:找出字母g后面的字母不是u的

import re
words=['gold','Google','Sogu','Guess']
patt=re.compile(r'.*g[^u]')

for w in words:
m=re.match(patt,w)
if m:
print (w)
>>>
gold
Google

函数

re.match方法

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None

参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

匹配对象方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
re.match例子
import re
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")

>>>
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter

re.search方法

re.search 扫描整个字符串并返回第一个成功的匹配。

re.search(pattern, string, flags=0)
参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

匹配成功re.search方法返回一个匹配的对象,否则返回None。
同样,可以用group()来获得结果.

匹配对象方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
re.search例子
import re
line = "Cats are smarter than dogs";
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
if searchObj:
print "searchObj.group() : ", searchObj.group()
print "searchObj.group(1) : ", searchObj.group(1)
print "searchObj.group(2) : ", searchObj.group(2)
else:
print "Nothing found!!"
>>>
searchObj.group() : Cats are smarter than dogs
searchObj.group(1) : Cats
searchObj.group(2) : smarter
re.match和re.search的区别
  • match在只能str开头寻找,不匹配则返回None
  • search则在str任意位置寻找

    re.sub方法

    Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。
    re.sub(pattern, repl, string, count=0, flags=0)
参数 描述
pattern 正则中的模式字符串
repl 替换的字符串,也可为一个函数
string 要被查找替换的原始字符串
count 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配
re.sub例子
import re
phone = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码是: ", num)
# 删除非数字(-)的字符串
num = re.sub(r'\D', "", phone)
print ("电话号码是 : ", num)
>>>
电话号码是: 2004-959-559
电话号码是 : 2004959559
repl 参数是一个函数时

以下实例中将字符串中的匹配的数字乘于 2:

import re
# 将匹配的数字乘于 2
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))

>>>
A46G8HFD1134

re.compile方法

ompile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

语法格式为:

re.compile(pattern[, flags])
参数 描述
pattern 一个字符串形式的正则表达式
flags 可选,表示匹配模式,比如忽略大小写,多行模式等
re.compile例子
import re
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小写
m = pattern.match('Hello World Wide Web')

>>> m.group(1) # 返回第一个分组匹配成功的子串
'Hello'
>>> m.span(1) # 返回第一个分组匹配成功的子串的索引
(0, 5)
>>> m.groups() # 等价于 (m.group(1), m.group(2), ...)
('Hello', 'World')

re.finditer方法

在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

re.finditer(pattern, string, flags=0)
参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
re.finditer例子
import re
it = re.finditer(r"\d+","12a32bc43jf3")
for match in it:
print (match.group() )
>>>
12
32
43
3

re.split方法

re.split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

re.split(pattern, string[, maxsplit=0, flags=0])
参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串
maxsplit 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
re.split例子
>>> re.split('\W+', ' runoob, runoob, runoob.', 1)   #\W	匹配非字母数字及下划线,匹配一次
['', 'runoob, runoob, runoob.']

>>> re.split('a*', 'hello world') # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['hello world']

附录

正则修饰符

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志
flags修饰符:

参数 描述
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

正则模式详表

模式 描述
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[…] 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,’m’或’k’
[^…] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n} 匹配n个前面表达式。。例如,”o{2}”不能匹配”Bob”中的”o”,但是能匹配”food”中的两个o。
re{ n,} 精确匹配n个前面表达式。例如,”o{2,}”不能匹配”Bob”中的”o”,但能匹配”foooood”中的所有o。”o{1,}”等价于”o+”。”o{0,}”则等价于”o*”。
re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
(re) 匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 类似 (…), 但是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#…) 注释.
(?= re) 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
(?> re) 匹配的独立模式,省去回溯。
\w 匹配字母数字及下划线
\W 匹配非字母数字及下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f].
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9].
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配”never” 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B 匹配非单词边界。’er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\n, \t, 匹配一个换行符。匹配一个制表符。等
\1…\9 匹配第n个分组的内容。
\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

常用匹配

字符类
实例 描述
[Pp]ython 匹配 “Python” 或 “python”
rub[ye] 匹配 “ruby” 或 “rube”
[aeiou] 匹配中括号内的任意一个字母
[0-9] 匹配任何数字。类似于 [0123456789]
[a-z] 匹配任何小写字母
[A-Z] 匹配任何大写字母
[a-zA-Z0-9] 匹配任何字母及数字
[^aeiou] 除了aeiou字母以外的所有字符
[^0-9] 匹配除了数字外的字符
特殊字符类
实例 描述
. 匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\w 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。
\W 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。

声明

本文中的部分例子来自菜鸟教程。
-------------本文结束感谢您的阅读-------------