xe5xb0x8fxe7x86x8a

Python的正则表达式运用

正则表达式(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 = 'home\ben\sales'

print(re.sub('\\', '/', str1))

并没有得到我们想要的结果,而且还报错了。这是因为字符串的转义和正则的转义冲突了,\\经过字符串转义后就成了\,而这时正则表达式分析器会认为这个正则表达式不完整,在一个完整的的正则表达式里,字符\的后面永远跟着另一个字符

所以在遇到上面这些字符时,就需要二次转义。这个例子除了\\还有\b也要经过二次转义

import re

str1 = '\home\ben\sales'

str2 = re.sub('\\\b', '/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-width: 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-width: 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('\w\d\w\d\w\d', str1))
# 》》['A1C2E3', 'M1B4F2', 'H1H2H2']

 

3. 匹配空白字符与非空白字符

\s 匹配任何一个空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
\S 匹配任何一个非空白字符。等价于 [^ \f\n\r\t\v]

注意用来匹配退格字符的[\b]元字符是一个特例:它不在类元字符\s的覆盖范围内,当然也就没有被排除在类元字符\S的覆盖范围外
4. 匹配十六进制或八进制数值
在正则表达式里,十六进制(逢16进1)数值要用前缀\x来给出。比如说,\x0A对应于ASCII字符10(换行符),其效果等价于\n。八进制(逢8进1)数值要用前缀\0来给出,数值本身可以是两位或三位数字。比如说,\011对应于ASCII字符9(制表符),其效果等价于\t

 













(部分内容摘自Ben Forta的《正则表达式必知必会》)

posted on 2020-04-28 00:19  牡蛎君  阅读(530)  评论(0编辑  收藏  举报

导航