正则表达式
描述了一种字符串匹配的模式(pattern),可以用来检查一个字符串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
- 可以通过正则表达式来查找和检索文档中的特定文本
- 可以通过正则表达式来替换文本或删除文本
- 可以基于正则表达式从字符串中提取子字符串
Re
Python提供re模块,包含所有正则表达式的功能。
import re
常用函数
一. match函数
re.match(pattern, string, flags=0)
pattern 匹配的正则表达式
string 要匹配的字符串
flags 标志位, 正则表达式修饰符
- 从头开始匹配, 匹配成功,返回一个Match对象,否则返回None
- 只匹配一次,找到匹配结果则不进行继续匹配
- 使用group()/group(0)获得匹配到的结果
- 使用span()可以获取到匹配结果的下标区间
- 如果需要分组获取匹配结果, 可以使用括号,并指定group(1)/group(2)等获得对应分组结果
- groups()表示获取所有分组结果并以元组返回
练习
-
判断网址’www.runoob.com’里面是否以’www’开头
从头匹配,符合返回匹配对象
str = ‘www.runoob.com’
pattern = ‘www’
res = re.match(pattern,str)
print(res)
“”"<_sre.SRE_Match object; span=(0, 3), match=‘www’>"""从头匹配,不符合返回none
str2 = ‘www.runoob.com’
pattern = ‘runoob’
res = re.match(pattern,str2)
print(res)
“”“None”""只匹配一次
str3 = ‘wwwwww.runoob.com’
pattern = ‘www’
res = re.match(pattern,str3)
“”"<_sre.SRE_Match object; span=(0, 3), match=‘www’>"""print(res.group())
print(res.group(0))获取部分/分组匹配结果
str2 = ‘runoob.com’
pattern = ‘(run)(oob)’
res = re.match(pattern,str2)
print(res.group())
print(res.group(1))
print(res.group(2))
print(res.groups())
练习
str = """<div>我是一个人</div>"""
str1 = """<div>你好世界</div><div>我是一个人</div>"""
str2 = """<div>我是一个人</div><div>我是一个人</div>"""
pattern = '<div>我是一个人</div>'
res = re.match(pattern,str)
匹配模式
-
点: \n除外的任意一个字符
-
加号: 匹配1次或多次
-
星号: 匹配0次或多次
判断str是否含有子串’i’,并且是以其开头
str = ‘i love you’
pattern = ‘i’
res = re.match(pattern,str)
print(res)任意一个字符
str = ‘i love you’
str = ‘l love you’
str = ‘\n love you’
str = ‘we love you’
str = ‘anyone love you’
pattern = ‘i love you’
pattern2 = ‘. love you’
pattern3 = ‘.+ love you’
pattern4 = ‘.* love you’
res = re.match(pattern,str)
print(res)text = “Cats are smarter than dogs”
text = “”“你好世界我是一个人”""
text = ‘我和你’ #(.?)
贪婪模式与非贪婪模式
# 贪婪模式与非贪婪模式
str = 'howareyouhowareyou'
# .* .*?
pattern = 'how.*you'
pattern1 = 'how.*?you'
# .+ .+?
pattern2 = 'how.+are'
pattern3 = 'how.+?are'
res = re.match(pattern,str)
res1 = re.match(pattern1,str)
res2 = re.match(pattern2,str)
res3 = re.match(pattern3,str)
print(res)
print(res1)
print(res2)
print(res3)
# . .?
text = '我和你'
text = '我和和和你'
text = '我你'
pattern = '我.你'
text = '我和你'
text = '我和和和你'
text = '我你'
pattern = '我.?你'
注意
"""
. 匹配任意一个除了\n以外的字符
.* 匹配任意除了\n以外,0次到多次的字符, 默认贪婪模式
.+ 匹配任意除了\n以外,1次到多次的字符, 默认贪婪模式
.? 匹配任意除了\n以外,0次到1次
.*? 匹配任意除了\n以外,0次到多次的字符, 默认非贪婪模式
.+? 匹配任意除了\n以外,1次到多次的字符, 默认非贪婪模式
"""
二. search函数
re.search(pattern, string, flags=0)
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位, 正则表达式修饰符 - 可选标志
- 从任意位置匹配,直到结束,匹配成功,返回匹配对象,否则返回None
- 只匹配一次, 匹配成功即结束匹配
- 使用group()/group(0)获得匹配到的结果
- 使用span()可以获取到匹配结果的下标区间
- 如果需要分组获取匹配结果, 可以使用括号,并指定group(1)/group(2)等获得对应分组结果
- groups()表示获取所有分组结果并以元组返回
a = 'www.runoob.com'
print(re.search('www', 'www.runoob.com').span())
print(re.search('runoob', 'www.runoob.com').span())
a = """<div>我是一个人</div>"""
b = """<div>你好世界</div><div>我是一个人</div>"""
c = """<div>我是一个人</div><div>我是一个人</div>"""
match() 和search() 的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;
而re.search匹配整个字符串,直到找到一个匹配,没有匹配到返回None
匹配模式
^ 以指定字符开头
a = 'i love you'
a = 'do i love you'
pattern = '^i love you'
$ 以指定字符结尾
text = 'i love you'
text = 'i love you,too'
pattern = 'i love you$'
或 |
text = 'sss'
text = '127'
text = '127sss'
pattern = 'sss|127'
res = re.search(pattern, text)
print(res.group())
[ ]
pattern = '[0-9]'
pattern = '[0-9]+'
text = '120293'
- [0-9] == [0123456789]
- [a-c] == [abc]
- [ABC] == [A-C]
^ 非
text = '123dfjsb'
pattern = '[^1]'
pattern = '[^2]'
pattern = '[^2]*'
pattern = '[^1]*'
pattern = '[^1]+'
[ \f\r\t\n ]
匹配所有空白字符
换页 回车 制表符 换行
re{n, m}
匹配 n 到 m 次由前面的正则表达式定义的片段,默认贪婪
re{n,}
匹配至少n 个
pattern = 'o{2,}'
text = 'Bob'
text = "foooood"
"o{1,}" == "o+"
"o{0,}" == "o*"
re{n}
固定匹配次数
注意
鼓励大家记住并使用 *、+ 和 ?,因为这些字符更短并且更容易阅读, 还有一个原因是匹配引擎对 * + ? 做了优化,效率要更高些
特殊字符类
\d
匹配任意一个数字, 等价于[0-9]
pattern = '\d'
pattern = '\d\d'
pattern = '^f\d*'
pattern = '^\d+'
\D
匹配任意一个非数字, 等价于 [^0-9]
\s
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
patttern = '\s+'
patttern = '\S+'
text = ' dwiefhew dwehfiow ehfdiewhfw '
res = re.search(patttern, text)
res = re.match(patttern, text)
\S
匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\w
匹配数字字母下划线。等价于'[A-Za-z0-9_]'
\W
匹配任何非数字字母下划线。等价于 '[^A-Za-z0-9_]'
修饰符(大写)
re.S : 使 . 匹配包括换行在内的所有字符
text = 'women\n'
pattern = 'women.'
res = re.search(pattern,text, re.S)
re.I : 使匹配对大小写不敏感
text = 'woMEn'
pattern = 'women'
res = re.search(parttern,text,re.I)
练习
1. 表单的邮箱验证
用户输入邮箱进行表单验证, 最多错五次, 如果5次内没有输入正确, 提示邮箱锁定
# text = input('请输入你的邮箱:')
pattern = '^[0-9a-zA-Z_]+@[0-9a-zA-Z_]+\.com$'
# if re.search(pattern, text):
# print('邮箱格式正确~~~~')
# else:
# print('什么破邮箱!!!!!')
2.【多选】
正则表达式A*B可以匹配
a. A
b. ACD
c. AB
d. AAB
3.【单选】
关于正则表达式,下列说法正确的是:
a. \w用来匹配数字
b. a?表示匹配0到多个a
c. re.I修饰符表示忽略大小写
3.【多选】
以下哪个字符串不能被正则表达式 a(bc?)d 匹配到?
a. abcd
b. abd
c. abc
d. acd
常用函数
findall()
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表
match 和 search 是匹配一次 findall 匹配所有
a = 'djwh0jwdhw0dwjbed0'
a = 'djwhjwdhwdwjbed'
res = re.findall('[a-z]+',a)
finditer()
在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回
text = 'i want to go home'
pattern = '[a-z]+'
res = re.finditer(pattern,text)
for i in res:
print(i.group())
compile()
可以将模式单独定义, 大数据量时可以提高性能
reg = re.compile(pattern)
res = reg.search(text)
lines = [
'i wang to eat ',
'i wang to eat ',
'i wang to eat ',
'i wang to eat ',
]
for i in lines:
res = re.search('[a-z]+]',i).group()
print(res)
reg = re.compile('[a-z+]]')
for i in lines:
res = reg.search(i).group()
print(res)
sub()
re.sub(pattern, repl, string)
-
pattern : 被替换的正则表达式
-
repl : 替换字符串
-
string : 被替换的原始字符串
text = ‘i love you’
res = re.sub(‘love’, ‘not love’, text)
print(res)
练习
将以下电话号码处理成纯数字
str = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python注释
res = re.sub('#.*$','',str)
res = re.sub('-','',res)
print(res)
# 或
res = re.sub('[^\d]+','',str)
print(res)
# 或
res = re.sub('\D+','',str)
# 爬虫中经常会用到sub来去除响应正文中的空白字符
text = 'xdjsh dweuhfwuei euwegf ub ue cudbcu'
res = re.sub('\s+', '', text)
print(res)
元字符
大多数字母和字符会匹配它们自身, 有少数特殊的字符我们称之为元字符(metacharacter),它们并不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等特殊功能
元字符
. ^ $ * + ? { } [ ] | ( )
转义
反斜杠 \
如果在反斜杠后边紧跟着一个元字符,那么元字符的“特殊功能”不会被触发。例如你需要匹配符号 [ 或 \,你可以在它们前面加上一个反斜杠,以消除它们的特殊功能
s = '. ^ $ * + ? { } [ ] \ | ( )'
res = re.findall('\$', s)
res = re.findall('\.', s)
res = re.findall('\( \)', s)
res = re.findall('\[ \]', s)
练习题
匹配一行文字中的所有开头的字母内容
s="i love you not because of who you are, but because of who i am when i am with you"
提取出所有副词
text = "He was carefully disguised but captured quickly by police."
pattern = '([a-zA-Z-])[a-zA-Z-]*'
pattern = '[a-zA-Z]+ly'
爬虫练习
百姓网