正则表达式
语法
单字符匹配
字符 | 匹配 |
---|---|
. | 匹配任意字符('\n’除外) |
\d | 匹配任意数字 |
\D | 匹配任意非数字 |
\s | 匹配空白字符(\t,\n,\r和空格) |
\S | 匹配任意非空白字符 |
\w | 匹配a-z和A-Z以及数字和下划线 |
\W | 与\w相反 |
[] | 只要满足括号中的某一项都算匹配成功 |
match方法总是从第一个字符匹配,返回group结构数据,若第一个字符不匹配返回空,报类型错误
import re
text = 'abc'
#match方法从第一个字符匹配,若不同返回空,报类型错误
#匹配某个字符
ret = re.match('a',text)#参1:规则,参2:源
print(ret.group())#结果:a
ret = re.match('b',text)#参1:规则,参2:源
print(ret.group())#结果:报错
#点(.):匹配任意字符('\n'除外)
ret = re.match('.',text) #res:a,匹配到'\n'报错
#\d:匹配任意数字
ret = re.match('\d',text)
#\D:匹配任意非数字
#\s:匹配空白字符(\t,\n,\r和空格)
#\S:匹配任意非空白字符
#\w:匹配a-z和A-Z以及数字和下划线
#\W:与\w相反
#[]组合方式,只要满足中括号中的某一项都算匹配成功
ret = re.match('[ab]',text)#能够匹配a或b,[]在引号内
ret = re.match('[0-9a-zA-Z_]',text)#\w
ret = re.match('[0-9]',text)#匹配0-9,同\d
ret = re.match('[^0-9]',text)#加^为取反,匹配非0-9,同\D
多字符匹配
字符 | 匹配 |
---|---|
* | 匹配前一个字符0次或无限次 |
+ | 匹配前一个字符1次或无限次 |
? | 匹配前一个字符0次或1次 |
{m}/{m,n} | 匹配前一个字符m次或m-n次 |
*? /+? /?? | 匹配模式变为非贪婪(尽可能少匹配字符) |
import re
text = 'abc'
text1 = '+abc'
#匹配任意多个字符
ret = re.match('\w*',text)#任意个字母数字下划线
print(ret.group())#结果:abc
ret = re.match('\w*',text1)#可以为0个,不报错,为空字符。
#+:匹配1个或多个
ret = re.match('\w+',text1)#报错。
#?:匹配0个或1个
ret = re.match('\w?',text)#res:a
#{m}:匹配m个
ret = re.match('\w{2}',text)#res:ab
#{m,n}:匹配m个
ret = re.match('\w{1,3}',text)#res:abc
ret = re.match('\w{1,3}','a+bc')#res:a
案例
多字符或匹配用:(xxx|xxx|xxx)表示
import re
#1.验证手机号:以1开头,第二位为34587,后面9位为数字
res = re.match("1[34587]\d{9}",'18660282235')
#2.验证邮箱:邮箱名符合变量定义,接@,后面为域名
res = re.match("\w+@[a-z0-9]+\.[a-z]+",'_song6367@qq.com')
#3.验证URL:以http,https,ftp开头,接'://',接非空白字符
res = re.match("(http|https|ftp)://\S+",'https://www.baidu.com')
#4.身份证号:18位,前17位为数字,后面可以是数字或x或X
res = re.match("\d{17}[\dxX]",'37100219881023556X')
开始、结束和非贪婪
re.search搜索整个字符串中,查找第一个满足条件的内容,只能查找一个。
import re
text = 'hello world'
# ^:以...为开头,即整个字符串以此开头,相当于match
res = re.search('^world',text)#错误
res = re.search('world',text)#res:world
# $:以...为结尾
res = re.search('hello$',text)#错误
# |:匹配多个字符串或者表达式
res = re.search('^world',text)#错误
# 贪婪和非贪婪
res = re.search('\w+?',text)#res:h,+?或*?等表示非贪婪模式,最小匹配
res = re.search('\w?+',text)#res:hello,?为首字符0或1次适配\w,仍为贪婪模式
# 案例1:提取html标签名称
text = '<h1>hello world</h1>'
res = re.search('<.+>',text) #res:<h1>hello world</h1>,贪婪模式
res = re.search('<.+?>',text) #res:<h1>,非贪婪模式
#验证一个字符是不是0-100之间的数字
res = re.match('(0|[1-9]\d?|100)','01234') #res:0,若以0开头,必须以0结尾,故加$
res = re.match('(0$|[1-9]\d?|100)','100') #res:10,若匹配两位数,则符合以此结尾,故加$
res = re.match('(0$|[1-9]\d?$|100)','1000') #res:100,若为三位数,则符合以此结尾,加$
res = re.match('(0$|[1-9]\d?$|100$)','1000') #报错
转义字符和原生字符
import re
#python中的转义字符:
text = 'hello\nworld' #\n为换行
text = 'hello\\nworld' #转义,转为字符"\n"
text = r'hello\nworld' #原生字符串,只认为是字符"\n"
#正则表达式中的转义字符
text = 'apple price is $99,range price is $88'
res = re.findall('$\d+',text)#res:[],$为以前面字符结尾,即以空白字符结尾
res = re.findall('\$\d+',text)#res:['$99','$88'],转义为$
#原生字符串和正则表达式
#转义规则:先原python语言中转义,然后将结果放在正则表达式中转义
text = '\cba c'
res = re.match('\c',text)#报错,正则遇'\',默认与后面字符结合,结果'\c'无意义
res = re.match('\\c',text)#报错,先python转为\c,正则表达式接收字符为'\c',结果同上
res = re.match('\\\c',text)#正确,python转为\\c,正则表达式转为'\c'
res = re.match(r'\\c',text)#报错,python不解析,正则表达式接收字符为'\c',结果同上
分组
正则表达式只能匹配一个字符串,要提出多个信息,需将目标信息的匹配规则用’()'括起来,通过group()获取,其中:
group()/group(0):匹配整个分组
group(n):匹配第一个分组,第一个为1
groups():以元组形式,返回所有分组
import re
text = 'apple price is $99,range price is $88'
res = re.search(r'.+(\$\d+).+(\s\d+)',text)
#group()/group(0):apple price is $99,range price is $88
#group(1):$99
#groups():('$99','$88')
常用函数
import re
text = 'apple price is $99,range price is $88'
html = '''
<div class = 'job-detail'>
<p>1.xxxxx</p>
<p>2.xxxxx</p>
</div>
'''
#findall:查找所有满足条件的,返回列表
res = re.findall(r'\$\d+',text)#res:['$99','$88']
#查找特殊字符间文本,不包括特殊字符。将需要提取字段加()
ruler = r'<p>(.+)</p>' #由于有括号,建议将表达式单独写出
res = re.findall(ruler ,html)#res:['1.xxxxx', '2.xxxxx']
#sub:根据规则替换其他字符串,可用于去除标签,比replace功能强大
res = re.sub(r'<.+?>','','html')#参1:表达式,参2:替换字符串,参3:源
'''res:
class = 'job-detail'
1.xxxxx
2.xxxxx
'''
#多条件替换,去除年月日
dateDel = re.sub('20\d\d年|\d{1,2}月|\d{1,2}日','',txt)
#split:根据规则分割字符串,可以指定多个分割符
res = re.split(r' |,',text)
#res:['apple', 'price', 'is', '$99', 'range', 'price', 'is', '$88']
#compile:编译正则表达式,对于多请求时,可提前编译好,防止每个请求都要编译一次
r = re.compile(r' |,')#编译正则表达式
res = re.split(r,text)#直接使用编译好的正则表达式
#re.VERBOSE:添加注释,防止后续看不懂
text = 'apple price is 34.56'
r = re.compile(r"""
\d+ # 整数部分
\.? # 小数点,可无,可出现1次
\d+ # 小数部分
""",re.VERBOSE)
#r = re.complie(r'\d+\.?\d+',text)#等价,正则表达式过于难懂,建议加注释
res = re.search(r,text)
'''search中也可加注释
res = re.search(r"""
\d+ # 整数部分
\.? # 小数点,可无,可出现1次
\d+ # 小数部分
""",text,re.VERBOSE)
'''
汉字
匹配多个汉字,不包括空格
import re
res = re.match(r'[\u4E00-\u9FA5]+', '我是 汉字')
print(res) # <re.Match object; span=(0, 2), match='我是'>
匹配多个汉字,包括空格
import re
res = re.match(r'[\u4E00-\u9FA5\s]+', '我是 汉字')
print(res) # <re.Match object; span=(0, 5), match='我是 汉字'>
匹配一个汉字
import re
res = re.match(r'[\u4E00-\u9FA5]', '我是 汉字')
print(res) # <re.Match object; span=(0, 1), match='我'>
import re
res = re.match(r'[^\x00-\xff]', '我是 汉字')
print(res) # <re.Match object; span=(0, 1), match='我'>