一篇文章搞定正则表达式

正则表达式是爬虫,Web开发,数据处理等各类涉及到文本处理的一把锋利的瑞士军刀,是每个程序员必须掌握的一门技能。

1. 正则表达式的7个层级

假设有一段文字:

text = '身高:178,体重:168,学号:123456,密码:9527'

要确定文本中是否包含数字123456,我们可以用in运算符,也可以使用index函数:

text = '身高:178,体重:168,学号:123456,密码:9527'target = '123456'if target in text:print('找到了')print(text.index(target))

但当问题变得复杂的时候,比如找出字符串中所有数字,用基本的字符串处理就不行了。

这不再是一个固定的字符串匹配问题,而是一个模式,一种规则的匹配。

为了解决这个问题,有位叫Stephen的大神在1951年提出了正则表达式。几乎任何一门通用编程语言都有专门的正则表达式的模块,正则表达式英文是regular expressesion,

所以编程语言中的模块名字一般叫re,或者regex等。

Python中的正则表达式处理模块是re。正则表达式就是为了找到符合某种模式的字符串,这些模式包括:是什么字符,重复多少次,在什么位置,有哪些额外的约束。

请注意:这里的每一句话都对应了正则表达式中的一类语法。

1)固定的字符串

要求:确定字符串中是否有123456

import retext = '麦叔身高:178,体重:168,学号:123456,密码:9527'print(re.findall(r'123456', text))

代码说明:

第1行,引入正则表达式模块re

第3行,使用re的findall()方法找到所有符合模式的字符串,这里的模式就是123456,也就是说找到字符串中所有的123456。

findall()方法的第1个参数是模式,第2个参数是要查找的字符串。模式中会有一些特殊字符,所以用r表示这是一个raw字符串,

让Python不要去转义里面的特殊字符。上面程序的运行结果是:[123456],因为整个字符串中就1个123456。

level1就是一个固定的字符串匹配,可以用传统的字符串匹配解决。

2) - 某一类字符

要求:找出所有的单个的数字

text = '麦叔身高:178,体重:168,学号:123456,密码:9527'print(re.findall(r'\d', text))

这个表达式

\d

表示所有的数字,所以1,7,8,1,6,8等都可以匹配到。这是很简单的模式,只匹配1个单独的数字。

如果你完全没有接触过正则表达式,看着有点懵逼,去我看在B站的视频吧,让我手把手教你!

3) - 重复某一类字符

要求:找所有的数字,比如178,168,123456,9527等。

text = '麦叔身高:178,体重:168,学号:123456,密码:9527'print(re.findall(r'\d+', text))

这个模式

\d+

在\d的后面增加了+号,表示数字可以出现1到多次,所以178等都符合它的要求。

4 )- 组合level2

要求:找出座机号码

text = '麦叔电话是18812345678,他还有一个电话号码是18887654321,他爱好的数字是01234567891,他的座机是:0571-52152166'print(re.findall(r'\d{4}-\d{8}', text))

\d{4}-\d{8}

这是一个组合的模式,表示前面4个数字,中间一个横杠,后面8个数字。

这里会匹配一个结果:0571-52152166

5 - 多种情况

要求:找出手机号码或者座机号码

text = '麦叔电话是18812345678,他还有一个电话号码是18887654321,他爱好的数字是01234567891,他的座机是:0571-52152166'print(re.findall(r'\d{4}-\d{8}|1\d{10}', text))

比上面有复杂了点,因为使用竖线(|)来表示”或“的关系,就是手机号码和电话号码都可以。

这里会匹配三个结果:18812345678,18887654321,0571-52152166。

6 - 限定位置

要求:在句子开头的手机号码,或座机

text = '18812345678,他还有一个电话号码是18887654321,他爱好的数字是01234567891,他的座机是:0571-52152166'print(re.findall(r'^1\d{10}|^\d{4}-\d{8}', text))

在表达式的最开始使用了^符号,表示一定要在句子的开头才行。这时候只有18812345678能匹配上。

7 - 内部约束

要求:找出形如barbar, dardar的前后三个字母重复的字符串

text = 'barbar carcar harhel'print(re.findall(r'(\w{3})(\1)', text))

这里barbar和carcar会匹配上,但harhel不会被匹配,因为它不是3个字符重复的。

\w{3}表示3个字符,放在小括号中(\w{3})就成为一个分组,而后面的(\1)表示它里面的内容和第1个括号里的内容必须相同,其中的1就表示第1个括号,也就是说3个字符要重复出现两次。

2. 写正则表达式的步骤

如何写正则表达式呢?我总结了几个步骤。不管多复杂,基本上都百试不爽。

我们仍然以包含分机号码的座机电话号码为例,比如0571-88776655-9527,演示下面的步骤:

确定模式包含几个子模式

  • 它包含3个子模式:0571-88776655-9527。
  • 这3个子模式用固定字符连接。
  • 各个部分的字符分类是什么这3个子模式都是数字类型,可以用\d。
  • 现在可以写出模式为:\d-\d-\d
  • 各个子模式如何重复:

            第1个子模式重复3到4次,因为有010和021等直辖市第2个子模式重复7到8次,

           有的地区只有7位电话号码第3个子模式重复3-4次加上次数限制后,

          模式成为:\d{3,4}-\d{7,8}-\d{3,4}但有的座机没有分机号,

          所以我们用或运算符让它支持两者:\d{3,4}-\d{7,8}-\d{3,4}|\d{3,4}-\d{7,8}

  • 是否有外部位置限制
  • 没有
  • 是否有内部制约关系
  • 没有
  • 经过一通分析,最后的正则就写成了,测试一下:
  • text = '随机数字:01234567891,座机1:0571-52152166,
  • 座机2:0571-52152188-1234'print(re.findall(r'\d{3,4}-\d{7,8}-\d{3,4}|\d{3,4}-\d{7,8}', text))
  • 最后的结果是:两个座机都可以找出来。

3. 语法规则

正则表达式几十个符号,看似很复杂,但如果能否分清楚类别和作用,就没那么复杂了。

  • 字符类别表达- 表达某一类字符,比如数字,字母,3到9之间的任何数字等

     

  • 字符的重复次数,也叫做量词。比如身份证是数字重复15或18次,也就是:\d{15}或者\d{18}。

     

  • 组合模式:把多个简单的模式组合在一起,可以是拼接,也可以是二者选其一。

     

  • 位置:限定模式出现的位置,比如行首,行尾,或者在特定字符之后等。

     

  • 分组,把一个正则表达式分成几个部分,这样可以重复某个分组,或者指定两个分组必须相同等额外的要求。

     

  • 其他:

4. Python正则模块re的用法

  • python的re模块还比较简单,包括以下几个方法:
  • re.search():查找符合模式的字符,只返回第一个,返回Match对象
  • re.match():和search一样,但要求必须从字符串开头匹配
  • re.findall():返回所有匹配的字符串列表
  • re.finditer():返回一个迭代器,其中包含所有的匹配,也就是Match对象
  • re.sub():替换匹配的字符串,返回替换完成的文本
  • re.subn():替换匹配的字符串,返回替换完成的文本和替换的次数
  • re.split():用匹配表达式的字符串做分隔符分割原字符串
  • re.compile():把正则表达式编译成一个对象,方便后面使用

5. 更多例子

下面举了更多的例子,供大家练习和熟悉。

  • 建议先自己尝试去写出相关的正则表达式,再回来看下面的参考答案。
  • 匹配Email地址的正则表达式
  • 匹配网址URL的正则表达式
  • 匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线)匹配国内电话号码(0571-87655322,001-87666622,920-209642-964)
  • 匹配腾讯qq号
  • 匹配中国邮政编码(6位数字)
  • 匹配身份证(15位或18位)
  • 匹配ip地址形如"carcar"或"barbar"等会重复的三个字符的单词
  • ==============分隔符==============
  • 现在来看参考答案:
  • 匹配Email地址的正则表达式:
  • \w+([-+.]\w+)*@\w+([-.]\w+)*.\w+([-.]\w+)*
  • 匹配网址URL的正则表达式:[a-zA-z]+://[^s]*
  • 匹配帐号是否合法(字母开头,允许5-16字母,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
  • 匹配国内电话号码,格式为:区号-号码-分机号,分机号可能没有。d{3,4}-d{7,8}-d{3,4}|d{3,4}-d{7,8}
  • 匹配腾讯qq号:[1-9][0-9]{4,}
  • 匹配中国邮政编码(6位数字):[1-9]\d{5}(?!\d)
  • 匹配身份证(15位或18位):\d{15}|\d{18}
  • 匹配ip地址:\d+.\d+.\d+.\d+形如"carcar"或"barbar"等会重复的三个字符的单词(\w{3})(\1)获取以"密码:"开头的数字:(?<=密码.)\d+

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值