使用re模块可以采用预编译然后使用编译过的方法,也可以不编译就直接使用函数,但无论是方法还是函数,名字都是一样的

介绍的方法/函数:

match(), search(), sub(), subn(),findall(),finditer,split(),compile()

表达式符号:
表达式符号 作用
re1|re2 匹配表达式 re1 或表达式 re2
. 匹配任意一字符(除了\n)
^ 匹配字符串起始部分
$ 匹配字符串终止部分
* 匹配 0 或多次前面出现的字符
+ 匹配 1 次或多次前面出现的字符
匹配 0 或 1 次前面出现的字符
{N} 匹配 N 次前面出现的正则表达式
[…] 匹配字符集的任一字符
[^…] 不匹配字符集里的任意字符
[x-y] 匹配 x~y 中的任意字符
(…) 匹配里头封闭的正则表达式,并存为一个分组
特殊字符:
特殊字符 作用
\d 匹配十进制数字字符,与 [0-9] 一致,相反为 \D
\w 匹配任意字母或数字字符,与[A-Za-z0-9] 一到处,相反为 \W
\s 匹配任何空格字符,与 [\n\t\r\v\f] 相同,相反 \S
\b 匹配任何单词边界, 相反 \B
\N 匹配已存的子组
\A(\Z) 匹配字符串的起始(结束)
使用 re
import re

下面以一个应用场景来介绍

你需要处理一个电话薄,需要里面的电话号码是这样的:
xxxx-xxxxxxx,如:0777-8888888
对应的正则表达式:r'\d{4}-\d{7}'
免责声明:下面提到的号码相关的正则表达式仅供参考

match() 匹配字符串

作用:从字符串的起始部分进行匹配
函数使用:re.match(<正则表达式>, <用来匹配的字符串>)

完全匹配

>>> re.match(r'0777-8888888','0777-8888888')
<re.Match object; span=(0, 12), match='0777-8888888'> #匹配成功,返回一个匹配对象
'0777-8888888'成功匹配,返回一个匹配对象。如果匹配不成功的话则返回None

不完全匹配

>>> re.match(r'\d{4}-\d{7}','abc0777-8888888') #匹配失败,返回None
>>> re.match(r'\d{4}-\d{7}','0777-8888888abc')
<re.Match object; span=(0, 12), match='0777-8888888'>
因为是从字符串起始部分匹配,所以 'abc0777-8888888' 匹配失败,没有返回值,如果不想从起始位置匹配,可以使用下面将要介绍的 search()
search() 查找匹配字符串

作用:搜索任何位置匹配的字符串
函数使用:re.search(<正则表达式>, <用来匹配的字符串>)

>>> re.search(r'\d{4}-\d{7}','abc0777-8888888def')
<re.Match object; span=(3, 15), match='0777-8888888'>

跟 match() 不一样的地方是 search() 是查找匹配的模式,任意位置的字符串都能被匹配到

匹配多个字符串“|”

假如现在不仅要匹配电话号码,还要匹配手机号码(如:+86-133123456789),这时就需要匹配多个字符串,可以使用择一匹配符号“|”。
正则表达式:r'\d{4}-\d{7}|+86-\d{11}'

>>> r = r'\d{4}-\d{7}|\+86-\d{11}'
>>> re.search(r,'18888888888')
>>> re.search(r,'+86-18888888888')
<re.Match object; span=(0, 15), match='+86-18888888888'>
>>> re.match(r,'0777-8888888')
<re.Match object; span=(0, 12), match='0777-8888888'>
匹配对象的方法 group()

当匹配到字符串时我们会得到一个匹配对象,可以用group()方法,返回匹配的字符串

>>> r = r'\d{4}-\d{7}|\+86-\d{11}'>>> m = re.search(r,'+86-18888888888')
>>> if m is not None:
...     m.group()
...
'+86-18888888888'

使用 if 去判断是否为空是因为当字符串不匹配时会返回 None 而不是一个匹配对象,这时调用方法group() 会报错 AttributeError
还有另外一个方法 groups() 后面会讲到

使用字符集 “[…]”

手机号码并不是全部的11位数就能匹配的,只有像 188 开头的才可能是手机号码,使用字符集来筛选
正则表达式:r'1[3,5,7,8,9]\d{9}'
表示以1开头,第二位为3,5,7,8或9的11位数字组合,[…] 表示匹配里面中的任一一个字符

>>> r = r'1[3,5,7,8,9]\d{9}'
>>> m = re.match(r,'18812345678')
>>> m.group()
'18812345678'
>>> re.match(r,'123123456789')
分组“ (…) ”

显然上面的手机号码正则表达式还远不及需求,133开头可能是手机号码,但如果134开头的不是呢,这时可以使用分组

>>> r = r'1(33|35|37|57|77|88|97)\d{8}'
>>> re.match(r,'13512345678')
<re.Match object; span=(0, 11), match='13512345678'>
>>> re.match(r,'13412345678')   # 匹配不到

如果我们把之前的电话号码分组,如:r'(\d{4})-(\d{7})'

>>> r = r'(\d{4})-(\d{7})'
>>> m = re.match(r, '0777-1234567')
>>> m.group()
'0777-1234567'
>>> m.group(0)
'0777-1234567'
>>> m.group(1)
'0777'
>>> m.group(2)
'1234567'
>>> m.groups()
('0777', '1234567')
再论匹配对象方法:group() 和 groups()

group() 用于以普通的方式显示所有的匹配部分,加上编号可用于获取各个匹配的子组
groups()方法用来获取一个包含所有子组的字符串元组

>>> r = r'(\d{4})-(\d{7})'
>>> m = re.match(r, '0777-1234567')
>>> m.group()          # 完整匹配
'0777-1234567'
>>> m.group(0)        #完整匹配
'0777-1234567'
>>> m.group(1)        #子组1
'0777'
>>> m.group(2)        #子组2
'1234567'
>>> m.groups()        #全部子组
('0777', '1234567')
>>> r = r'\d{4}-\d{7}'
>>> m = re.match(r, '0777-1234567abcd')
>>> m.group()
'0777-1234567'
>>> m.groups()        #没有子组
()
限制匹配字符串的起始和结尾边界:“^”(起始) 和 “$”(结尾)

r'^\d{4}-\d{7}' 表示起始匹配正则表达式
r'\d{4}-\d{7}$' 表示结尾匹配正则表达式
r'^\d{4}-\d{7}$' 表示起始和结尾结尾匹配正则表达式

>>> r = r'\d{4}-\d{7}$'   #设置结束边界
>>> m = re.match(r, '0777-1234567')
>>> if m is not None:
...     m.group()
...
'0777-1234567'
>>> m = re.search(r, '0777-1234567')
>>> m.group()
'0777-1234567'
>>> m = re.search(r, '0777-1234567abcd')
>>> if m is not None:
...     m.group()
…                        #没匹配到
>>> r = r'^\d{4}-\d{7}'   #设置起始边界
>>> re.search(r, 'abcd0777-12345677')
>>>             #没匹配到
findall() 和 finditer() 查找每个出现的位置

作用:相询全部不重复出现的字符串
使用:
re.findall(<正则表达式>, <作用的字符串>)
re.finditer(<正则表达式>, <作用的字符串>)

>>> r = r'\d{4}-\d{7}'
>>> re.findall(r, 'Tom:0111-1111111,Bob:0222-2222222')
['0111-1111111', '0222-2222222']
>>> re.findall(r, 'Tom:0000,Bob:0000')
[]

与 match() 和 search() 不同的是 findall() 相询全部不重复出现的字符串,并一直返回一个列表,匹配不到也是一个空的字符表。不重复是什么意思呢?如:

>>> r = r'\d{4}-\d{7}'
>>> re.findall(r,'0770-1234567-1234567')
['0770-1234567']

上面的列子字符串可匹配的情况有0770-1234567和4567-1234567,但由于4567在第一次查询已经使用,不会被重复使用,所以下次查词是从-1234567开始查找

使用分组,让findall() 只返回子组匹配的内容,如想只提取电话号码中的号码而不含区号,可以这样做

>>> r = r'\d{4}-(\d{7})'
>>> re.findall(r, 'Tom:0111-1111111,Bob:0222-2222222')
['1111111', '2222222']

finditer(),和findall()类似,但finditer返回的是一个迭代器,能节省内存的使用

>>> r = r'(\d{4})-(\d{7})'
>>> m = re.finditer(r,'Tom:0111-1111111,Bob:0222-2222222')
>>> [x.groups() for x in m]
[('0111', '1111111'), ('0222', '2222222')]
>>> m = re.finditer(r,'Tom:0111-1111111,Bob:0222-2222222')
>>> m.__next__().groups()
('0111', '1111111')
>>> m.__next__().groups()
('0222', '2222222')
使用 sub() 和 subn() 搜索并替换

作用:搜索匹配的字符串部分并以某种形式做替换
使用:

re.sub(<正则表达式>, <用来替换的字符串>, <作用字符串>)
re.subn(<正则表达式>, <用来替换的字符串>, <作用字符串>)

如:‘Miss.Tom:0111-1111111,Miss.Bob:0222-2222222’,想替换用户信息中的称呼“Miss”为 “Mr”

>>> re.sub('Miss', 'Mr','Miss.Tom:0111-1111111,Miss.Bob:0222-2222222')
'Mr.Tom:0111-1111111,Mr.Bob:0222-2222222'
>>> re.subn('Miss', 'Mr','Miss.Tom:0111-1111111,Miss.Bob:0222-2222222')
('Mr.Tom:0111-1111111,Mr.Bob:0222-2222222', 2)

可以看出subn还回返回一个替换的总数

还有一个神奇的用法。分组调换,使用 \N 来调用分组,N 表示分组编号
如:下面出现称呼和名称位置错位,调换过来

>>> info = 'TomMr.:0111-1111111,BobMr.:0222-2222222'
>>> re.sub(r'(\w+)(Mr\.)(\:\d{4}-\d{7})',  r'\2\1\3', info)
'Mr.Tom:0111-1111111,Mr.Bob:0222-2222222'
split() 分隔字符串

作用:分割字符串,返回一个列表
使用:re.split(<分割位置字符串>, <被分割字符串>)

如:基于“:”字符分割

>>> re.split(':','Mr.Tom:0111-1111111,Mr.Bob:0222-2222222')
['Mr.Tom', '0111-1111111,Mr.Bob', '0222-2222222']
>>> re.split(':','Mr.Tom:0111-1111111,Mr.Bob:0222-2222222',1) #指定最大分割次数
['Mr.Tom', '0111-1111111,Mr.Bob:0222-2222222']
使用 compile() 做预编译

使用 compile() 可以将正则表达式预编译为一个对象,接着就可以重复调用该正则表达式

>>> c = re.compile(r'\d{4}-(\d{7})')
>>> c.search('Mr.Tom:0111-1111111,Mr.Bob:0222-2222222')
<re.Match object; span=(7, 19), match='0111-1111111'>
>>> c.findall('Mr.Tom:0111-1111111,Mr.Bob:0222-2222222')
['1111111', '2222222']
贪婪匹配与非贪婪匹配

举个粟子
字符串:'<div>123</div><div>abcd</div>'
想提取 div 标签里的内容 123 和 abcd
正则表达式(贪婪匹配):r'<div>(\w.*)</div>'

>>> re.findall(r'<div>(\w.*)</div>', '<div>123</div><div>abcd</div>')
['123</div><div>abcd']

正则表达式(非贪婪匹配):r'<div>(\w.*?)</div>'

>>> re.findall(r'<div>(\w.*?)</div>', '<div>123</div><div>abcd</div>')
['123', 'abcd']

“?”在这里表示以尽量少的次数匹配

参考自:《Python 核心编程(第三版)》

这篇博客介绍 python 的 re 模块的相关函数/方法,及一些相关符号使用相关推荐

  1. 我的第一篇博客:Python爬取新浪财经股票页面 并用matplotlib可视化输出结果

    (由于疫情在家闲着,开学至少得等到四月份,便在上个星期动起了学习python的念头,凭借着大一C语言微薄的基础草草学习语法后便开始了学写爬虫.跟着教学视频爬了几个静态网站后便开始尝试爬动态网站,同时也 ...

  2. 第100篇博客——用Python爬取我前99篇博客内容,分词并生成词云图

    这是我的第100篇博客,从2016年7月1日发表第一篇博客至今,也有两个多年头了. 回首自己前99篇博客,各种类型都有,有技术总结,有随感,有读书笔记,也有BUG修改.内容千奇百怪,质量参差不齐,篇幅 ...

  3. 号称史上最牛逼的几篇博客整理(python+java+js等)

    号称史上最牛逼的几篇博客这个说法也许夸张了点,但总体来说楼主整理的博客都是楼主幸苦之作,并且都是围绕去转盘网展开,这些博客几乎透漏了该站的所有技术关键,细节,甚至所有核心代码,我个人认为作为一个有艺术 ...

  4. fiddler软件+手机模拟器搭配抓包,这篇博客有Python爬虫与百家号的事

    本篇博客为爬虫120例第60例,核心内容围绕手机抓包展开,本片练习模拟器与 Fiddler 之间的搭配 . 选择模拟器的原因也很简单,由于很多抓包软件对安卓系统有版本要求,我们不能天天给手机更换系统, ...

  5. 第一篇博客,python爬取淘宝信息

    python爬取淘宝信息 本人只是刚学python的菜鸟,代码不规范及需改进的地方请指教 我们直接看代码吧!哈哈 import requests from bs4 import BeautifulSo ...

  6. 2022年从零开始,用一篇博客掌握 nginx 的初级配置

    本篇博客主要用于记录 nginx.conf 这一个文件如何修改的相关问题. 当 nginx 安装之后,默认的配置如下所示(数据来源为宝塔自动生成),本篇博客重点介绍的是配置虚拟机相关内容,即 serv ...

  7. 学C/C++想提升功底 可以花点时间看看这篇博客---C语言程序环境和预处理

    本篇博客介绍了C语言程序环境和预处理.主要包含程序的翻译和运行环境和 各种预处理操作:预定义符号.各种#define 用法 undef的使用条件编译的使用 头文件包含指令 C语言程序环境和预处理 一. ...

  8. Linux--进程(一篇博客让你理解操作系统的底层)

    Linux–进程 本篇博客讲开始进入进程模块,我们先从冯诺依曼的体系结构和操作系统讲起,由浅入深,先梳理一个Linux相关知识体系框架~ 进程目录 Linux--进程 一.冯诺依曼体系结构 1.1外围 ...

  9. 如果你不了解 python 的学习体系?来看看这篇博客吧 ,特邀嘴强擦哥做点评|Python技能树测评

    这是一次联动写作~ 特邀擦哥为大家介绍 C 站一款新产品,<python 技能树>.内测地址为 https://bbs.csdn.net/skill/python. 内测版的技能树,是对 ...

最新文章

  1. 手把手教你如何配置fiddler、并开启手机代理抓包、最详细
  2. 38. Count and Say
  3. pxe+kickstart无人值守安装
  4. 2011年度最佳 jQuery 插件发布
  5. apollo 配置中心_apollo-1:apollo配置中心单机模拟分布式部署
  6. java ews_Java---使用EWS 写个ExchangeMailUtil
  7. 函数2——*args/**kwargs、作用域、函数的嵌套、关键字globa和nonlocal、函数的注释...
  8. php兼容net的md5,解决c# md5与php md5加密不一致的问题(md5(unicode))
  9. Struts学习总结(一)---搭建Struts框架
  10. matlab simulink 汽车制动纵向动力学建模
  11. 计算机一级考试试题在线操作,计算机一级考试题库操作题
  12. 小程序:uniapp开发和原生开发语法区别
  13. 获取打印机状态,判断打印机状态,获取打印机驱动信息
  14. 扩展名是.class.php,php 获取文件扩展名的函数 - strtolower
  15. python条形码识别_使用Python和OpenCV在视频中实时监测条形码
  16. [机器学习导论]——第三课——神经网络Ⅱ
  17. 物料编码的方法与技术
  18. 转载与积累系列 - Docker 核心技术与实现原理
  19. QKL123 | 区块链排行榜
  20. 你可能不了解的《唐诗三百首》

热门文章

  1. C语言实现通讯录(含文件保存)
  2. 最详细的Excel模块Openpyxl教程——基础操作
  3. 【基于人脸特征的心率检测研究】非接触式光电容积图和红外人脸视频瞬时心率估计
  4. linux设置sfq队列参数,Linux内核中流量控制(5)
  5. TI DM36X 名词
  6. css_min-height、max-height、height详细讲解
  7. JAVA核心知识点--IO流
  8. Zeppelin安装教程
  9. U盘安装ubuntu20.04并优化
  10. Pr入门系列之十五:校色与调色