正则表达式,就是使用定义好的特定字符组成一个“规则字符串”,来描述、匹配一系列符合其规则的字符串。也就是说,通过正则表达式,我们可以按照一定的匹配规则从字符串中提取出我们想要的数据。
一、匹配规则
1.普通字符
因为普通字符的匹配规则是一个具体的字符串,所以其匹配的灵活性非常有限。
import re
target='Life is short,I learn python.'
result=re.findall('python',target)
print(result)
# 得到的结果是['python']
result1=re.findall('java',target)
print(result1)
# 得到的结果是[]
如果匹配规则是一个普通字符串的话,我们只能从内容中提取出确定的数据,而如果想要提取的数据是变化着的,比如时间,显然这种匹配规则就不适用了。
2.元字符
①字符集
字符集,用[]表示,中括号内可以写任意字符,各字符间是“或”的关系。该位置上的字符如果在字符集的范围内则匹配成功。
import re
target='abc acc aec agc adc aic'
result=re.findall('a[de]c',target)
print(result)
# 得到的结果是['aec', 'adc']
result1=re.findall('a[b-z]c',target)
print(result1)
# 得到的结果是['abc', 'acc', 'aec', 'agc', 'adc', 'aic']
result2=re.findall('a[^c-z]c',target)
print(result2)
# 得到的结果是['abc']
②概括字符集
概括字符集,用""+字母表示,表示该位置的字符类型,一般与数量词一起使用。该位置上的字符如果属于该类型则匹配成功。
import re
target='Python3.8'
result=re.findall(r'd',target)
print(result)
# 得到的结果是['3', '8']
result1=re.findall(r'D',target)
print(result1)
# 得到的结果是['P', 'y', 't', 'h', 'o', 'n', '.']
result2=re.findall(r'w',target)
print(result2)
# 得到的结果是['P', 'y', 't', 'h', 'o', 'n', '3', '8']
result3=re.findall(r'W',target)
print(result3)
# 得到的结果是['.']
result4=re.findall(r's',target)
print(result4)
# 得到的结果是[]
result5=re.findall(r'S',target)
print(result5)
# 得到的结果是['P', 'y', 't', 'h', 'o', 'n', '3', '.', '8']
③数量词
数量词,有{}、?、+、*等,表示该位置前面的字符或字符类型出现的次数,一般结合概括字符集实现某些功能。该位置前的字符或字符类型出现的次数如果在数量词的范围内则匹配成功。
import re
target='To be or not to be,that is a question'
result=re.findall(r'w{1,7}',target)# 这一行表示把字母或_1-7的长度匹配出来
print(result)
# 得到的结果是['To', 'be', 'or', 'not', 'to', 'be', 'that', 'is', 'a', 'questio', 'n']
result1=re.findall(r'w+',target)# 这一行表示把字母或_大于或等于1的长度匹配出来
print(result1)
# 得到的结果是['To', 'be', 'or', 'not', 'to', 'be', 'that', 'is', 'a', 'question']
target='点赞数:120'
result2=re.findall(r'd{1,2}',target)# 这一行表示把数字1-2的长度匹配出来
print(result2)
# 得到的结果是['12', '0']
result3=re.findall(r'd+',target)# 这一行表示把数字大于或等于1的长度匹配出来
print(result3)
# 得到的结果是['120']
*和?经常连在一起使用,属于下面贪婪和非贪婪的内容。
④边界匹配符
边界匹配符,有^、$等,表示开头或结尾的字符串。如果开头或结尾的字符串符合规则则匹配成功。
import re
result=re.findall('^http.*','https://www.zhihu.com')
print(result)
# 得到的结果是['https://www.zhihu.com']
result1=re.findall('^http.*','www.csdn.net')
print(result1)
# 得到的结果是[]
result2=re.findall('.*net$','https://www.zhihu.com')
print(result2)
# 得到的结果是[]
result3=re.findall('.*net$','www.csdn.net')
print(result3)
# 得到的结果是['www.csdn.net']
⑤贪婪与非贪婪
贪婪用.*表示,非贪婪用.*?表示,都表示除换行以外的任意字符。在使用到组的时候,贪婪模式会尽可能多地匹配字符串,非贪婪模式会尽可能少地匹配字符串。Python默认使用的是贪婪模式。
那什么是组呢?
import re
target='发布于2020/06/26'
result=re.findall(r'.*(d.*?d)',target)# 组外使用贪婪模式,会尽可能多地匹配字符串最后只剩26符合组的条件
print(result)
# 得到的结果是['26']
result1=re.findall(r'.*?(d.*d)',target)# 组外使用非贪婪模式,会尽可能少地匹配字符串以让符合组的条件范围最大化
print(result1)
# 得到的结果是['2020/06/26']
result2=re.findall(r'.*?(d.*?d)',target)# 组内组外同时使用非贪婪模式,让组内条件最大化的同时再进行细分
print(result2)
# 得到的结果是['20', '20', '06', '26']
3.修饰符
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志,较为常用的有re.I和re.S。
例1:
import re
target='LIFE IS TOO SHORT'
result=re.findall('^life.*short$',target)
print(result)
# 得到的结果是[]
result1=re.findall('^life.*short$',target,re.I)
print(result1)
# 得到的结果是['LIFE IS TOO SHORT']
例2:
import re
target='''Life is too short,
I learn python'''
result=re.findall('^Life.*python$',target)
print(result)
# 得到的结果是[]
result1=re.findall('^Life.*python$',target,re.S)
print(result1)
# 得到的结果是['Life is too short,nI learn python']
二、常用函数
函数里有一些参数,它们代表的意思分别如下:
pattern:匹配规则
repl:替换字符串的字符串
string:待匹配的字符串
counts:最大替换次数
maxsplit:最大分割数,剩下的未分割的将作为列表的最后一个元素
flags:修饰符
1.findall(pattern,string,flags=0)
在给定字符串中搜索全部能匹配的字符串,返回列表类型。
import re
target='ZIP102600 ZIP102400'
result=re.findall(r'd+',target)
print(result)
# 得到的结果是['102600', '102400']
2.match(pattern,string,flags=0)
从给定字符串的开始位置起匹配正则表达式,返回的是match对象,使用group()取值。
import re
result=re.match(r'd+','点赞数:120')
if result:
print(result.group(0))
else:
print('None')
# 得到的结果是None
result1=re.match(r'd+','120 点赞数')
if result1:
print(result1.group(0))
else:
print('None')
# 得到的结果是120
使用match方法会从给定的字符串开头去匹配,没有匹配到就会直接返回None,所以这在做匹配的时候并不方便,它更适合用来检测某个字符串是否符合某个正则表达式的规则。
3.search(pattern,string,flags=0)
在给定字符串中搜索第一个匹配正则表达式的字符串,返回match对象,使用group()取值。
import re
result=re.search(r'd+','点赞数:120')
print(result.group(0))
# 得到的结果是120
与match相比,search也是从头开始匹配,不过只要其中有一个字符符合规则就会直接返回,但不会再往下继续匹配。
4.sub(pattern,repl,string,counts=0,flags=0)
从给定字符串中替换全部能匹配的字符串,返回替换后的字符串。
import re
target='ZIP102600 ZIP102400'
result=re.sub('ZIP','邮编',target)
print(result)
# 得到的结果是邮编102600 邮编102400
5.finditer(pattern,string,flags=0)
在给定字符串中搜索全部能匹配的字符串,返回一个可迭代对象,每个迭代元素是match类型,使用group()取值。
import re
target='ZIP102600 ZIP102400'
result=re.finditer(r'd+',target)
for m in result:
print(m.group(0))
'''
得到的结果是
102600
102400
'''
6.split(pattern,string,maxsplit=0,flags=0)
在给定字符串中按照正则表达式匹配结果进行分割,返回列表类型。
import re
target='ZIP102600 ZIP102400'
result=re.split(r'd+',target)
print(result)
# 得到的结果是['ZIP', ' ZIP', '']
result1=re.split(r'd+',target,maxsplit=1)
print(result1)
# 得到的结果是['ZIP', ' ZIP102400']
7.compile(pattern,flags=0)
编译一个正则表达式模式,返回一个模式对象。
import re
target="who you are,what you do,When you get get there? What is time you state there?"
pattern=re.compile(r'w*whw*',re.I)
result=pattern.findall(target)
print(result)
# 得到的结果是['who', 'what', 'When', 'What']
附:经典正则表达式实例
'^[A-Za-z]+$' # 由26个字母组成的字符串
'^[A-Za-z0-9]+$' # 由26个字母和数字组成的字符串
r'^-?d+$' # 整数形式的字符串
'^[0-9]*[1-9][0-9]*$'# 正整数形式的字符串
r'[1-9]d{5}' # 中国境内6位数的邮政编码
'[u4e00-u9fa5]' # 匹配中文字符
公众号:「Python编程小记」,持续推送学习分享,欢迎关注!