正则表达式(regular expression,简称regex)是文本处理方面功能最强大的工具之一。正则表达式语言用来构造正则表达式(最终构造出来的字符串就称为正则表达式),正则表达式用来完成搜索和替换操作
正则表达式语言是内置于其他语言或软件产品里的“迷你”语言,Python自1.5版本起增加了re
模块,它提供Perl风格的正则表达式模式
re模块常用函数
1. re.match
re.match尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
import re str1 = 'My name is Jim.' print(re.match('Jim', str1)) # 》》None print(re.match('My', str1)) # 》》<re.Match object; span=(0, 2), match='My'>
匹配成功会返回一个re.Match对象,否则返回None
然后可以使用group()函数来获取匹配表达式
import re str1 = 'My name is Jim.' print(re.match('My', str1).group()) # 》》My
2. re.search
re.search扫描整个字符串并返回第一个成功的匹配
import re str1 = 'My name is Jim.' print(re.match('Jim', str1)) # 》》None print(re.search('Jim', str1)) # 》》<re.Match object; span=(11, 14), match='Jim'>
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配
可以通过span()函数得到匹配对象的位置
import re str1 = 'My name is Jim.' print(re.search('My', str1).span()) # 》》(0, 2) print(re.search('Jim', str1).span()) # 》》(11, 14)
3. re.sub
re.sub用于替换字符串中的匹配项
import re str1 = 'My name is Jim.' print(re.sub('Jim', 'Kim', str1)) # 》》My name is Kim.
4. re.compile
compile函数用于编译正则表达式,生成一个正则表达式(Pattern)对象
import re str1 = 'My name is Jim.' pattern = re.compile('Jim') print(type(pattern)) # 》》<class 're.Pattern'> print(pattern.search(str1)) # 》》<re.Match object; span=(11, 14), match='Jim'>
5. re.findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表
注意:match和search是匹配一次,findall匹配所有
import re str1 = 'My name is Jim. Her name is Kim.' print(re.findall('name', str1)) # 》》['name', 'name']
6. re.finditer
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回
import re str1 = 'My name is Jim. Her name is Kim.' iterator = re.finditer('name', str1) print(type(iterator)) # 》》<class 'callable_iterator'> print([match.group() for match in iterator]) # 》》['name', 'name']
更详细的函数用法可以参考 https://www.runoob.com/python/python-reg-expressions.html
匹配单个字符
1. 匹配任意字符.
字符(英文句号)可以匹配除换行符以外的任何单个字符,字母、数字甚至是.字符本身
在同一个正则表达式里允许使用多个.字符
import re str1 = ''' sales1.xls orders3.xls sales2.xls sales3.xls apac1.xls europe2.xls na1.xls na2.xls sa1.xls ''' print(re.findall('.a.', str1)) # 》》['sal', 'sal', 'sal', 'pac', 'na1', 'na2', 'sa1'] print(re.findall('.a..', str1)) # 》》['sale', 'sale', 'sale', 'pac1', 'na1.', 'na2.', 'sa1.']
正则表达式匹配的并不总是整个字符串,而是与某个模式相匹配的字符——即使它们只是整个字符串的一部分
但如果想要的结果只有na1.、na2.和sa1.,就需要.a..的最后那个.表示.本身
2. 匹配特殊字符
.字符在正则表达式里有着特殊的含义,如果需要的是.字符本身而不是它在正则表达式里的特殊含义,必须在.的前面加上一个(反斜杠)字符来对它进行转义。是一个元字符(metacharacter,表示这个字符有特殊含义,而不是字符本身含义)
import re str1 = ''' sales1.xls orders3.xls sales2.xls sales3.xls apac1.xls europe2.xls na1.xls na2.xls sa1.xls ''' print(re.findall('.a..', str1)) # 》》['na1.', 'na2.', 'sa1.']
在正则表达式里,字符永远出现在一个有着特殊含义的字符序列的开头,这个序列可以由一个或多个字符构成
如果需要搜索本身,相应的转义序列是两个连续的反斜杠字符\,但是,Python在这里是有坑的
看下面例子,把路径里的反斜杠字符()替换为正斜杠字符(/)
import re str1 = 'homeensales' print(re.sub('\', '/', str1))
并没有得到我们想要的结果,而且还报错了。这是因为字符串的转义和正则的转义冲突了,\经过字符串转义后就成了,而这时正则表达式分析器会认为这个正则表达式不完整,在一个完整的的正则表达式里,字符的后面永远跟着另一个字符
所以在遇到上面这些字符时,就需要二次转义。这个例子除了\还有也要经过二次转义
import re str1 = 'homeensales' str2 = re.sub('\', '/b', str1) print(re.sub('\\', '/', str2)) # 》》/home/ben/sales
正则表达式经常被简称为模式(pattern),它们其实是一些由字符构成的字符串。这些字符可以是普通字符(纯文本)或元字符(有特殊含义的特殊字符)
匹配一组字符
1. 指定字符集合的匹配
在正则表达式里,可以使用元字符[和]
来定义一个字符集合
import re str1 = 'The phrase "regular expression" is often abbreviated as RegEx or regex.' print(re.findall('[Rr]eg[Ee]x', str1)) # 》》['RegEx', 'regex']
re模块match、search、sub、compile、finditer等函数都有一个flags参数,它是可选标志修饰符,上面例子的结果也可以通过re.I这个使匹配对大小写不敏感的匹配模式来实现
import re str1 = 'The phrase "regular expression" is often abbreviated as RegEx or regex.' iterator = re.finditer('regex', str1, re.I) print([match.group() for match in iterator]) # 》》['RegEx', 'regex']
2. 字符集合区间
在使用正则表达式的时候,会频繁的用到一些字符区间(0~9、A~Z等等)。为了简化字符区间的定义,正则表达式提供了一个特殊的元字符——字符区间可以用-
(连字符)来定义。-(连字符)作为元字符它只能用在[和]之间。在字符集合以为的地方,-只是一个普通字符,只能与-本身相匹配。因此,在正则表达式里,-字符不需要被转义
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母及数字 |
下面是查找RGB值(用一个十六进制数字给出的红、绿、蓝三基色的组合值)的例子↓
import re str1 = ''' #db-global-nav { height: 28px; color: #d5d5d5; background-color: #545652; min- 950px; } ''' print(re.findall( '#[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]', str1)) # 》》['#d5d5d5', '#545652']
3. 取非匹配
用元字符^来表明想对一个字符集合进行取非匹配。^的效果将作用于给定字符集合里的所有字符或字符区间,而不是仅限于紧跟在^字符后面的那一个字符或字符区间
import re str1 = ''' sales1.xls orders3.xls sales2.xls sales3.xls apac1.xls europe2.xls sam.xls na1.xls na2.xls sa1.xls ca1.xls ''' print(re.findall('[ns]a[^0-9].xls', str1)) # 》》['sam.xls']
类元字符
字符集合是最常见的匹配形式,而一些常用的字符集合可以用特殊元字符来代替。这些元字符匹配的是某一类别的字符(术语称之为“字符类”)
1. 匹配数字与非数字
d | 匹配一个数字字符。等价于 [0-9] |
D | 匹配一个非数字字符。等价于 [^0-9] |
import re str1 = ''' #db-global-nav { height: 28px; color: #d5d5d5; background-color: #545652; min- 950px; } ''' print(re.findall('dpx', str1)) # 》》['8px', '0px']
注意d和[0-9]匹配的都是一个数字字符,所以这个例子无法匹配到28px和950px
2. 匹配字母和数字与非字母和数字
w | 匹配任何一个字母数字字符(大小写均可)或下划线字符。等价于'[A-Za-z0-9_]' |
W | 匹配任何一个非字母数字或非下划线字符。等价于 '[^A-Za-z0-9_]' |
import re str1 = '11213 A1C2E3 48075 48237 M1B4F2 90046 H1H2H2' print(re.findall('wdwdwd', str1)) # 》》['A1C2E3', 'M1B4F2', 'H1H2H2']
3. 匹配空白字符与非空白字符
s | 匹配任何一个空白字符,包括空格、制表符、换页符等等。等价于 [ f v] |
S | 匹配任何一个非空白字符。等价于 [^ f v] |
注意用来匹配退格字符的[]元字符是一个特例:它不在类元字符s的覆盖范围内,当然也就没有被排除在类元字符S的覆盖范围外
4. 匹配十六进制或八进制数值
在正则表达式里,十六进制(逢16进1)数值要用前缀x来给出。比如说,x0A对应于ASCII字符10(换行符),其效果等价于
。八进制(逢8进1)数值要用前缀 来给出,数值本身可以是两位或三位数字。比如说, 11对应于ASCII字符9(制表符),其效果等价于
(部分内容摘自Ben Forta的《正则表达式必知必会》)