作者 by Joab / 2022-04-02 / 1 评论 / 89 个足迹
本文章转载至公众号:麦叔编程(回复re即可查看该文章)
正则表达式是爬虫,Web开发,数据处理等各类涉及到文本处理的一把锋利的瑞士军刀,是每个程序员必须掌握的一门技能。本文稍微有点长,但耐心看完,实践其中的例子,你的功力必会更精进一层!
如果你对正则表达式还是小白,强烈建议去B站看我的配套视频,在B站搜“麦叔编程 正则表达式”就可以找到了。
如果你已经有一定基础了,看本文应该就够了!
不管有没有基础,本文最后有我整理的正则表达式语法清单,建议下载保存!
假设有一段文字:
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。
正则表达式就是为了找到符合某种模式的字符串,这些模式包括:是什么字符,重复多少次,在什么位置,有哪些额外的约束。请注意:这里的每一句话都对应了正则表达式中的一类语法。
下面我们通过8个例子,来熟悉正则表达式,后面再讲写正则表达式的套路和正则表达式的语法。
要求:确定字符串中是否有123456
import retext = '麦叔身高:178,体重:168,学号:123456,密码:9527'print(re.findall(r'123456', text))
代码说明:
上面程序的运行结果是:[123456],因为整个字符串中就1个123456。
level1就是一个固定的字符串匹配,可以用传统的字符串匹配解决。
要求:找出所有的单个的数字
text = '麦叔身高:178,体重:168,学号:123456,密码:9527'print(re.findall(r'\d', text))
这个表达式\d
表示所有的数字,所以1,7,8,1,6,8等都可以匹配到。这是很简单的模式,只匹配1个单独的数字。
如果你完全没有接触过正则表达式,看着有点懵逼,去我看在B站的视频吧,让我手把手教你!
要求:找所有的数字,比如178,168,123456,9527等。
text = '麦叔身高:178,体重:168,学号:123456,密码:9527'print(re.findall(r'\d+', text))
这个模式\d+
在\d的后面增加了+号,表示数字可以出现1到多次,所以178等都符合它的要求。
要求:找出座机号码
text = '麦叔电话是18812345678,他还有一个电话号码是18887654321,他爱好的数字是01234567891,他的座机是:0571-52152166'print(re.findall(r'\d{4}-\d{8}', text))
\d{4}-\d{8}
这是一个组合的模式,表示前面4个数字,中间一个横杠,后面8个数字。
这里会匹配一个结果:0571-52152166
要求:找出手机号码或者座机号码
text = '麦叔电话是18812345678,他还有一个电话号码是18887654321,他爱好的数字是01234567891,他的座机是:0571-52152166'print(re.findall(r'\d{4}-\d{8}|1\d{10}', text))
比上面有复杂了点,因为使用竖线(|)来表示”或“的关系,就是手机号码和电话号码都可以。
这里会匹配三个结果:18812345678,18887654321,0571-52152166。
要求:在句子开头的手机号码,或座机
text = '18812345678,他还有一个电话号码是18887654321,他爱好的数字是01234567891,他的座机是:0571-52152166'print(re.findall(r'^1\d{10}|^\d{4}-\d{8}', text))
在表达式的最开始使用了^符号,表示一定要在句子的开头才行。这时候只有18812345678能匹配上。
要求:找出形如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个字符要重复出现两次。
如何写正则表达式呢?我总结了几个步骤。不管多复杂,基本上都百试不爽。
我们仍然以包含分机号码的座机电话号码为例,比如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))
最后的结果是:两个座机都可以找出来。
正则表达式几十个符号,看似很复杂,但如果能否分清楚类别和作用,就没那么复杂了。
python的re模块还比较简单,包括以下几个方法:
下面我举了更多的例子,供大家练习和熟悉。
建议先自己尝试去写出相关的正则表达式,再回来看下面的参考答案。
==============分隔符==============
现在来看参考答案:
\w+([-+.]\w+)*@\w+([-.]\w+)*.\w+([-.]\w+)*
[a-zA-z]+://[^s]*
^[a-zA-Z][a-zA-Z0-9_]{4,15}$
d{3,4}-d{7,8}-d{3,4}|d{3,4}-d{7,8}
[1-9][0-9]{4,}
[1-9]\d{5}(?!\d)
\d{15}|\d{18}
\d+.\d+.\d+.\d+
形如"carcar"或"barbar"等会重复的三个字符的单词
(\w{3})(\1)
获取以"密码:"开头的数字:
(?<=密码.)\d+
建议收藏和下载这个cheatsheet,在必要的时候查询。
如果对你有帮助,请给我点赞,并点在看,谢谢!
 评论 1 条