博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python之正则表达式(复杂篇)
阅读量:3907 次
发布时间:2019-05-23

本文共 4513 字,大约阅读时间需要 15 分钟。

前言

继上篇文章说了正则表达式的基础用法,那今天我们就继续说一下正则表达式的复杂的用法。好了,废话不多说,直接进入正题。

正文

情景:当你想要匹配一个qq号,qq号码长度为5-10位,那根据上篇文章的说法,很容易就可以想到该正则:

[0-9]{
5,10}

这样是可以的,但是当你匹配一个长度大于10的号码时就会出错,这时就会去该字符串的前10个数字出来,如下:

import rea='1234567890'r=re.findall('[0-9]{5,10}',a)#明显当查找的字符串长度大于8位时就会出错,只会截取前一部分长度print(r)

结果

['1234567890']

这样的话你就会得到一个错误的qq号码。

这时就需要引入边界匹配了:

  • ^:这个是从左边开始匹配,规定左边的首个字符
  • $:这个是从右边开始匹配,规定右边的首个字母

现在再写个匹配qq号码的正则:

r=re.findall('^[0-9]{5,10}$',a)#这个表示从左边起为5-10的数字长度,右边也是一样print('第一个匹配结果:',r)a = '1234567890'r=re.findall('^[0-9]{5,10}$',a)print('第二个匹配结果:',r)

结果

第一个匹配结果: []第二个匹配结果: ['1234567890']

这样就可以匹配到了,是不是很神奇?


:前面我们有用 [ ] 来匹配,中括号里面表示的是或关系,而这里的组表示的是并关系,并且用小括号括起来 ( )

比如:重复 python 字样三次

import rea='pythonpythonpythonjakjpythonpythonsdjjpythonpythonpythonsd'r=re.findall('(python){3}',a)print(r)

结果

['python', 'python']

这里的结果不是返回三个python,而是返回这个组,当符合一次就会将此组添加到返回列表中一次。

这个组还挺好用的,再看下这个需求:获取下列英文中的life和python之间的内容。

a='life is short,i use python'r=re.findall('life(.*)python',a,re.S)print(r) # 这样获取的就是组内的内容

结果

[' is short,i use ']

这个组还常用,因为在我们经常在用正则来解析html元素时,经常需要获取两个标签之间的内容,标签是确定的,标签内容不确定,就可以用这个了。如下这个html元素:

python进阶             python入门         vce解决方法         百度         反馈意见        下载图片     

这样就可以用组来获取a标签的内容了:<a .*?>(.*?)</a>。?表示非贪婪哦!

  • re.findall(pattern,string,flags):这个方法的前两个参数对你们来说都很熟悉了,第一个参数为正则表达式,第二个参数为要进行匹配的字符串,而第三个可选参数为匹配模式,有如下几种匹配模式:
  • re.I(re.IGNORECASE) :使匹配对大小写不敏感
  • re.L(re.LOCAL):做本地化识别(locale-aware)匹配
  • re.M(re.MULTILINE):多行匹配,影响 ^ 和 $
  • re.S(re.DOTALL):使 . 匹配包括换行在内的所有字符(这个常用)
  • re.U(re.UNICODE):根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
  • re.X(re.VERBOSE):该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解

当需要写多个匹配模式时,可以用 | 分隔每个模式

代码如下:

a='Java12Python89'r=re.findall('python',a,re.I)print(r)a='hsjhj h123jfkksf hajkGH\nkj fjfk'r=re.findall('.',a,re.I|re.S)print(r)

结果:

['Python']['h', 's', 'j', 'h', 'j', ' ', 'h', '1', '2', '3', 'j', 'f', 'k', 'k', 's', 'f', ' ', 'h', 'a', 'j', 'k', 'G', 'H', '\n', 'k', 'j', ' ', 'f', 'j', 'f', 'k']

正则除了可以用来检索字符串,还可以用来替换字符串,常见的可以用来替换那些文本中的空格,制表符和回车等,这些都是用一个正则就可以搞定的了。

python中用这个方法来进行正则替换

re.sub(pattern, repl, string, count=0, flags=0)

  • pattern :正则表达式
  • repl :替换后的字符串,可为函数
  • string :要进行替换的字符串
  • count :替换的次数,顺序为 从左往右,默认值为0,表示无限次。
  • falgs : 匹配模式,和findall()差不多

代码如下:

import rea='skjC#ksjfc#jkdsc#'r=re.sub('c#','gg',a)#返回值是替换后的字符串print(r)print(a)r=re.sub('c#','gg',a,1) # 这个加了替换次数print(r)r=re.sub('c#','gg',a,1,re.I) # 加了匹配模式,忽视大小写print(r)

结果

skjC#ksjfggjkdsggskjC#ksjfggjkdsc#skjggksjfc#jkdsc#

我们试试第二个参数为函数的情况

def convert(value):#他是把对象传进去这个参数    print(value)    #可以通过group()方法来获取内容    return '!!'+value.group()+"!!"r=re.sub('c#',convert,a,flags=re.I)#接收个参数后,更改后的内容为他的返回值print(r)

结果

<_sre.SRE_Match object; span=(3, 5), match='C#'><_sre.SRE_Match object; span=(9, 11), match='c#'><_sre.SRE_Match object; span=(15, 17), match='c#'>skj!!C#!!ksjf!!c#!!jkds!!c#!!

这个第二个参数为convert函数,里面的.group() 方法是获取匹配后的字符串的值,所以我们就可以根据匹配后的字符串来进行相对应的替换内容,比如这个简单的小需求:

把字符串中的数字大于50的改为99,小于的就改为11。

a='ds+45sd78asd12568asd45asd74ew+9ddf12sd45'def func(value):    if int(value.group())>50:        return '99'    else:        return '11'r=re.sub('\d{1,2}',func,a)print(r)

结果

ds+11sd99asd119911asd11asd99ew+11ddf11sd11

另谈两个函数

  • re.match(pattern,string,flags) :这个是从字符串的首个字母开始匹配,若首个字母不符合,就会返回None,
    反之返回一个 Match对象。而他只会匹配第一个结果,不会返回所有符合结果的内容。参数内容与findall()方法一样。
  • re.search(pattern,string,flags):这个与match方法差不多,不过不是从首字符开始匹配,也是只返回一个正确的匹配内容。

代码:

import rea='pythonphpjavacphp'r=re.match('php',a)#这个一开始没有就返回Noneprint(r)r=re.search('php',a)#这个搜索到之后就返回一个对象#返回的对象可以通过group()方法来获取他的内容print(r)# 获取匹配内容print(r.group())

结果

None<_sre.SRE_Match object; span=(6, 9), match='php'>php

这两个函数返回的内容的几个属性:

  • group() :获取匹配的内容
  • statr() :获取到匹配字符的起始位置
  • end() :获取匹配到字符的结束位置
  • span() :获取匹配到字符的起始和结束位置,元组形式返回。

前面提到组的概念,试下这两个方法的组的用法:

import re#获取life和python之间的内容a='life is short,i use python'r=re.search('life(.*)python',a,re.S)#用小括号的就是一组print(r.group(1))#这个下标1就是对应的中间部分#也可以获取中间的两部分a='javawoshipythonjunephp'r=re.search('java(.*)python(.*)php',a)#两个小括号就是分成了两组print(r.group(1),r.group(2))#分别打印第一第二组print(r.groups())#这个获取所有分组信息

结果:

is short,i use woshi june('woshi', 'june')

上面的代码注释已经很清楚了,还有个group()方法是获取整个正则匹配的内容,不按分组。match()方法也一样,就不演示了。

最后一个问题:怎样拆分含有多种分隔符的字符串?

比如:kfs;hsji’fhsikf*bhsfk=jsf/shj。要将不属于字母的都去掉,你是不是会想到用字符串的循环,然后再一个一个分割出来?我告诉你,学了正则之后,再也不用这么麻烦了。re库里面有个split()方法,如下:

re.split(pattern, string, maxsplit=0),参数看名字应该就能知道。直接一行代码进行分割:

a = 'kfs;hsjifhsikf*bhsfk=jsf/shj'r = re.split('[;*=/]', a)print(r)

结果:

['kfs', 'hsjifhsikf', 'bhsfk', 'jsf', 'shj']

是不是很完美?所以说正则必须得学!

总结

这个正则复杂点的已经说完了,还有些进阶的,不过暂时没有用到,就先不写了,有需要的可以百度。

正则表达式相关的jupyter的笔记已经上传的到我的GitHub上,有需要的可以下载下来看看,给个star也是可以的。

GitHub:

转载地址:http://oeren.baihongyu.com/

你可能感兴趣的文章
别“躺”着了,赶紧把「复盘」做起来
查看>>
真正拖垮你的,是沉没成本
查看>>
Docker:恢复对开源项目的无限制访问
查看>>
Blazor 准备好为企业服务了吗?
查看>>
.NET5全面拥抱Azure云,微软市值重回巅峰,那些年吹过的牛,都实现了!
查看>>
C# 中的 ref 已经被放开,或许你已经不认识了
查看>>
C#刷剑指Offer | 【常考题】最小的k个数
查看>>
【专题】多角度深入解析开放原子开源基金会
查看>>
在 Azure App Service 上启用 Application Request Routing
查看>>
使用 Xunit.DependencyInjection 改造测试项目
查看>>
谈谈.NET Core IServiceProvider
查看>>
一个.NET Core下的开源插件框架Pluginfactory
查看>>
基于阿里云日志服务快速打造简版业务监控看板
查看>>
集赞有礼!进击吧! Blazor !第六期 企业内部应用建设实战
查看>>
大象起舞——微软研发如何保持创新力和敏捷性
查看>>
Newbe.ObjectVisitor 0.2.10 发布,更花里胡哨
查看>>
寻找性能更优秀的动态 Getter 和 Setter 方案
查看>>
跟我一起学.NetCore之EF Core 实战入门,一看就会
查看>>
.NET架构小技巧(8)——优待异常
查看>>
一款基于.NET Core的认证授权解决方案-葫芦藤1.0开源啦
查看>>