正则表达式
正则表达式有多重要,这可是上古神兽,任何语言都不能忽略的技能槽。
国际惯例,需要官方无微不至的关怀的请出门左转:正则表达式HOWT
白话正则
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。 例,你想在一堆人名中找和你同名的人,描述语法为:
不管你姓啥,名字叫'明'站出来。
来试一试正则的魅力:
import re
names = '''
小小明
小明
小头
大明
大大明
大头
'''
m = re.findall(r'.+明', names, re.M)
print(m)
输出:
['小小明', '小明', '大明', '大大明']
正则表达式语法规则
正则表达式是一套独立于语言之外的语法规则,各种语言都遵守这套规则来实现了正则匹配,最基础的正则语法(需熟练掌握):
常用的元字符
语法 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
重复
语法 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
分枝
使用
|
标识分歧,可类比编程语言中的‘或’
固定电话号码正则:
0\d{2}-\d{8}|0\d{3}-\d{7}
匹配两种以连字号分隔的电话号码: 1. 3位区号,8位本地号(如001-12345678); 2. 4位区号,7位本地号(0123-1234567)。
分组
使用
( )
标识分组:
IP地址正则:
(\d{1,3}\.){3}\d{1,3}
- \d{1,3}匹配1到3位的数字;
- (\d{1,3}.){3}匹配三位数字加上一个英文句号(分组)重复3次;
- 最后再加上一个一到三位的数字(\d{1,3})
反义
使用
^
标识取反:
匹配用尖括号括起来的以a开头的字符串
<a[^>]+>
语法 | 说明 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
基础语法规则实践
模式 | 描述 |
---|---|
[Pp]ython | 匹配 "Python" 或 "python" |
[0-9] | 匹配任何数字。类似于 [0123456789] |
[a-z] | 匹配任何小写字母 |
[^0-9] | 匹配除了数字外的字符 |
主要函数
现在尝试再用正则的语法去理解上述代码,我们首先导入了re
模块,这是Python内置的正则模块。
它实现了很多功能,包括且不限于'match'
,'search'
,'findall'
等等。
findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
match
尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None。
import re
# 在起始位置匹配成功匹配到www,并使用span返回了匹配成功的位置元祖数据
print(re.match('www', 'www.easypython.cn').span())
# 起始位置匹配匹配easypython失败返回None
print(re.match('easypython', 'www.easypython.cn'))
输出:
(0, 3)
None
group(num) 或 groups()
使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
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
search
扫描整个字符串并返回第一个成功的匹配。
search
和match
不同的地方在于,
search
搜索整个字符串,任意子串符合正则就算成功匹配;
而match
是从开始位置进行匹配,字符串开始不符合正则表达式,则匹配失败。
import re
#找到符合正则表达式的子串就使用span返回了匹配成功的位置元祖数据
print(re.search('www', 'www.easypython.cn').span())
print(re.search('easypython', 'www.easypython.cn').span())
输出:
(0, 3)
(4, 14)
compile
compile
函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match()
和 search()
使用。
import re
pattern = re.compile('easypython')
print(pattern.search('www.easypython.cn').span())
sub
sub用于替换字符串中的匹配项。
import re
site = 'www.笔者.cn'
site = re.sub('笔者', "easypython", site)
print(site)
split
split 方法按照能够匹配的子串将字符串分割后返回列表
import re
strs = re.split('\W+','www.easypython.cn')
print(strs)
#输出 ['www', 'easypython', 'cn']