python3.5学习笔记(第六章)
本章内容:
正则表达式详解(re模块)
1、不使用正则表达式来查找文本的内容
要求从一个字符串中查找电话号码,并判断是否匹配制定的模式,如:555-555-5555。传统的查找方法如下:
def isPhoneNumber(text):
if len(text) != 12:
return False
for i in range(0,3):
if not text[i].isdecimal():
return False
if text[3] !='-':
return False
for i in range(4,7):
if not text[i].isdecimal():
return False
if text[7] !='-':
return False
for i in range(8,12):
if not text[i].isdecimal():
return False
return True message = "Call me at 415-232-2354 tomorrow. 415-234-2545 is my office."
for i in range(len(message)):
chunk = message[i:i+12]
if isPhoneNumber(chunk):
print('Phone number found:'+chunk)
print('Done')
>>>
Phone number found:415-232-2354
Phone number found:415-234-2545
Done
解析:在for循环的每一次迭代中,取自message的一段新的12个字符被赋值给变量chunk,将chunk传递给isPhoneNumber(),看是否符合电话号码的模式,如果符合就打印出这段文本。最终该循环遍历整个字符串。
2、用正则表达式查找文本模式
正则表达式,简称regex,是文本模式的描述方法。比如 \d\d\d-\d\d\d-\d\d\d\d 可以匹配 3个数字,一个短线,3个数字,一个短线,4个数字,也就是上面说的电话号码的格式。
在一个模式后面加上花括号包围的数字,比如 {3} ,就是说匹配这个模式3次。所以上面的 \d\d\d-\d\d\d-\d\d\d\d 可以表示为 \d{3}-\d{3}-\d{4} 。
2.1 创建正则表达式对象
python中的所有正则表达式的函数都在re模块中,使用前要先导入该模块。
import re
向 re.compile() 传入一个字符串,表示正则表达式,它将返回一个Regex模式对象。
phone_number_regex = re.compile(r'\d{3}-\d{3}-\d{4}')
2.2 匹配Regex对象
Regex对象的search()方法查找传入的字符串,寻找该正则表达式的所有匹配。如果没有找到,则返回None;如果找到了,则返回一个Match对象。Match对象有一个group()方法,它返回被查找字符串中实际匹配的文本。
import re
#正则表达式返回全部文本
phone_number_regex = re.compile(r'\d{3}-\d{3}-\d{4}') #{3}表示这个表达式匹配3次
mo = phone_number_regex.search('My number is 515-555-5555')
print('Phone number found:'+ mo.group()) #mo是一个Match对象,需要调用group()方法才会打印实际匹配到的文本
>>>
Phone number found:515-555-5555
2.3 正则表达式匹配小结
(1)用import re 导入正则表达式模块。
(2)用re.compile() 函数创建一个Regex对象(要使用原始字符串)。
(3)向Regex对象的search()方法传入想要查找的字符串,会返回一个Match对象。
(4)调用Match对象的group()方法,返回实际匹配文本的字符串。
3、用正则表达式匹配更多的模式
3.1 利用括号分组
添加括号将在正则表达式中创建分组没然后可以利用group方法从一个分组中获取匹配的文本。
在正则表达式中,第一对括号是第一组,第二对括号是第二组。向group传入参数1或2,就可以取得匹配到的文本中的不同部分(分组),向group传入参数0或者不传入参数,将会取得匹配到的文本的全部内容。
import re
phone_number_regex = re.compile(r'(\d{3})-(\d{3}-\d{4})')
mo = phone_number_regex.search('My number is 515-555-5555')
print('Phone number found:'+ mo.group(1))
>>>Phone number found:515
如果想要一次获得全部的分组,可以使用groups方法
import re
phone_number_regex = re.compile(r'(\d{3})-(\d{3}-\d{4})')
mo = phone_number_regex.search('My number is 515-555-5555')
g_1 ,g_2 = mo.groups()
print('g_1:',g_1)
print('g_2:',g_2)
>>>
g_1: 515
g_2: 555-5555
因为括号在正则表达式中默认用于分组,所以想要匹配真正的括号时需要对括号进行转义(两边都要转义)
import re
phone_number_regex = re.compile(r'(\(\d{3}\)) (\d{3}-\d{4})')
mo = phone_number_regex.search('My number is (515) 555-5555')
print('Phone number found:'+ mo.group(1))
>>>
Phone number found:(515)
3.2 用管道匹配多个分组
希望匹配多个表达式中的一个时,可以使用管道符 ‘|’ ,如果希望匹配的文本都出现在了被查找的字符串中,那么第一次出现的匹配文本将会作为Match对象被返回。
import re
hero_regex = re.compile(r'Batman|Tina Fey')
mo = hero_regex.search('Batman and Tina Fey')
print(mo.group())
>>>
Batman
也可以通过指定前缀和管道符组合,实现多个表达式的匹配。
import re
bat_regex = re.compile(r'Bat(man|mobile|copter|bat)') #Bat是前缀,与括号中内容进行组合。
mo1 = bat_regex.search('Batmobile lost a wheel')
print(mo1.group()) #返回完全匹配的文本
print(mo1.group(1)) #返回括号分组内匹配的文本
>>>
Batmobile
mobile
3.3 用问号实现可选匹配
字符 ?表示它前面的表达式或分组在这个模式中是可选的。但是?只匹配零次或一次。
import re
bat_Regex = re.compile(r'Bat(wo)?man')
mo_1 = bat_Regex.search('The Adventures of Batman')
mo_2 = bat_Regex.search('The Adventures of Batwoman')
mo_3 = bat_Regex.search('The Adventures of Batwowoman')
print(mo_1.group())
print(mo_2.group())
print(mo_3)
>>>
Batman
Batwoman
None
3.4 用星号 * 匹配零次或多次
星号 * 的匹配方式与 ?有所不同,星号 * 可以匹配多次即只要存在就可以匹配。
import re
bat_Regex = re.compile(r'Bat(wo)*man')
mo_1 = bat_Regex.search('The Adventures of Batwowowoman')
print(mo_1.group())
>>>
Batwowowoman
3.5 用加号 + 匹配一次或多次(至少匹配到一次)
import re
bat_Regex = re.compile(r'Bat(wo)+man')
mo_1 = bat_Regex.search('The Adventures of Batman')
mo_2 = bat_Regex.search('The Adventures of Batwoman')
mo_3 = bat_Regex.search('The Adventures of Batwowoman')
print(mo_1)
print(mo_2.group())
print(mo_3.group())
>>>
None
Batwoman
Batwowoman
3.6 用花括号匹配特定的次数
如果想要一个分组重复特定次数,就在正则表达式中该分组的后面,跟上一个花括号,括号中的数字表示重复的次数。如
phone_number_regex = re.compile(r'\d{3}-\d{3}-\d{4}')
除了制定一个数字,还可以制定一个范围,即在花括号后面写一个最小值a,一个最大值b,如{a,b}。
正则表达式{Ha}{3,5} 将匹配 ‘HaHaHa’、‘HaHaHaHa’ 和 ‘HaHaHaHaHa’ 。也可以省略第一个或者第二个数字,不限定最小值或最大值。
import re
ha_regex_1 = re.compile(r"(ha){3}")
m_1 = ha_regex_1.search('hahahaha')
print(m_1.group())
ha_regex_2 = re.compile(r'(ha){3,5}') #匹配3-5次,返回尽可能多的文本(贪心匹配)
m_2 = ha_regex_2.search('hahahahahaha')
print(m_2.group())
>>>
hahaha
hahahahaha
4、贪心和非贪心匹配
python的正则表达式默认是在有多种匹配结果的情况下,尽可能匹配最长的字符串。如果需要尽可能匹配最短的字符串,在花括号后面添加一个问号 ? 即可
import re
ha_regex_1 = re.compile(r'(ha){3,5}') #匹配3-5次,返回尽可能多的文本(贪心匹配)
m_1 = ha_regex_1.search('hahahahahaha')
print(m_1.group())
ha_regex_2 = re.compile(r'(ha){3,5}?') #匹配3-5次,返回尽可能多的文本(贪心匹配)
m_2 = ha_regex_2.search('hahahahahaha')
print(m_2.group())
>>>
hahahahaha
hahaha
注意: 问号在python中有两种含义:一种是表示匹配可选分组,另一种是声明非贪心匹配,要注意区分。
5、findall() 方法
search方法将返回被查找字符串中第一次匹配到的文本,而findall方法将返回被查找字符串中的匹配到的所有文本,findall返回的不是Match对象,而是一个字符串列表。
import re
phone_numbre_regex = re.compile(r'\d{3}-\d{3}-\d{4}')
phone_number = phone_numbre_regex.findall('Cell:555-555-5555 Work:888-888-8888')
print(phone_number)
>>>
['555-555-5555', '888-888-8888']
如果正则表达式中有分组,则返回元组的列表。
import re
phone_numbre_regex = re.compile(r'(\d{3})-(\d{3}-\d{4})')
phone_number = phone_numbre_regex.findall('Cell:555-555-5555 Work:888-888-8888')
print(phone_number)
>>>
[('', '555-5555'), ('', '888-8888')]
6、字符分类
常用字符分类的缩写代码
缩写字符分类 |
表示 |
\d | 0-9的任何数字 |
\D | 除0-9数字以外的任何字符 |
\w | 任何字母、数字、下划线字符(可以认为是匹配‘单词’字符) |
\W | 除字母、数字和下划线以外的任何字符 |
\s | 空格、制表符或换行符(可以认为是匹配‘空白’)字符 |
\S | 除空格、制表符和换行符之外的任何字符 |
7、建立自己的字符分类
可以用方括号 [ ] 建立自己的字符分类,比如[aeiouAEIOU]将匹配所有的元音字母,不论大小写。
import re
vowelregex = re.compile(r'[aeiouAEIOU]')
str_1 = vowelregex.findall('hsoaiejdpoaJEP WGEPAEF JFOPAWJE[oeofjgjop jfgawpe')
print(str_1)
也可以使用短横线表示字母或者数字的范围,比如字符分类[0-9a-zA-Z]将匹配所有的数字和大小写字母。
import re
vowelregex = re.compile(r'[0-9a-zA-Z]')
str_1 = vowelregex.findall('hlsijrg894w4t23\.wsew213^&*%^&$79832hiu we')
print(str_1)
注意在方括号中,普通的正则表达式符号均代表原本的意义,不需要进行转义。
通过在字符分类的左方括号右边添加一个插入字符 ^ ,就可以得到“非字符类”,也就是说正则表达式将匹配不在这个字符分类中的字符。
import re
vowelregex = re.compile(r'[^aeiouAEIOU]')
str_1 = vowelregex.findall('hsoaiej WGEPAEF JFJE[oeoop jfgawpe')
print(str_1)
8、插入字符和美元字符
可以在正则表达式的开始处使用插入字符^,表示匹配必须发生在被查找文本的开始处;
import re
begin = re.compile(r'^hello')
answer_1 = begin.search('hello world')
answer_2 = begin.search('world hello')
print(answer_1.group())
print(answer_2)
>>>
hello
None
同样,也可以在正则表达式的末尾添加一个美元字符$,表示该字符串必须以这个正则表达式的模式结束。
import re
begin = re.compile(r'hello$')
answer_1 = begin.search('hello world')
answer_2 = begin.search('world hello')
print(answer_1)
print(answer_2.group())
>>>
None
hello
可以同时使用插入符和美元字符,表示整个字符串必须匹配该模式,而不是只匹配其中的子集。
import re
begin = re.compile(r'^hello$')
answer_1 = begin.search('hello')
answer_2 = begin.search('world hello')
print(answer_1.group())
print(answer_2)
>>>
hello
None
9、通配字符
句点 . 被称为“通配符” 。它匹配除换行符之外的所有字符。但是句点只能匹配一个字符,比如r'.s' 只能匹配到 ‘us’,而不能匹配‘yours’。
import re
begin = re.compile(r'.')
answer_1 = begin.search('hello')
print(answer_1.group())
>>>
h
9.1 用点-星(.*)匹配所有的字符串,点-星表示任意文本。
import re
begin = re.compile(r'.*')
answer_1 = begin.search('hello')
print(answer_1.group())
>>>
hello
9.2 用句点字符匹配换行
如果想要用点-星匹配包括换行符在内的所有字符,可以通过给compile传入第二个参数re.DOTALL实现。
import re
begin = re.compile(r'.*',re.DOTALL)
answer_1 = begin.search('hello \nworld')
print(answer_1.group())
>>>
hello
world
10、正则表达式常用符号
? | 匹配零次或一次前面的分组 |
* | 匹配零次或多次前面的分组 |
+ | 匹配一次或多次前面的分组 |
{n} | 匹配n次前面的分组 |
{n,} | 匹配n次或更多次前面的分组 |
{,m} | 匹配零次到m次前面的分组 |
{n,m} | 匹配至少n次,至多m次前面的分组 |
{n,m}?或*?或+? | 对前面的分组进行非贪心匹配 |
^spam | 字符串必须以spam开始 |
spam$ | 字符串必须以spam结束 |
. | 匹配除换行符之外的所有字符 |
\d,\w,\s | 分别匹配数字、字母和空格 |
\D,\W,\S | 分别匹配除数字、字母和空格之外的所有字符 |
[abc] | 匹配方括号内的任意字符 |
[^abc] | 匹配不在方括号内的任意字符 |
11、不区分大小写的匹配
一般来说,正则表达式是区分大小写的,如果想要正则表达式不区分大小写,可以向re.compile()中传入re.I作为第二个参数。
import re
begin = re.compile(r'[a-z]*',re.I)
answer_1 = begin.search('ahisdhfliNILSHILHAI')
print(answer_1.group())
>>>
ahisdhfliNILSHILHAI
12、用sub()方法替换字符串
regex对象的sub方法需要传入两个参数,第一个参数是一个字符串,用于取代发现的匹配。第二个参数是一个字符串,是用正则表达式匹配的内容。sub方法返回替换完成后的字符串。
import re
name_regex = re.compile(r'world')
answer_1= name_regex.sub('小姐姐','hello world')
print(answer_1)
>>>
hello 小姐姐
13、管理复杂的正则表达式
通常正则表达式写成一段会很难阅读,所以可以将正则表达式写成多行字符串的形式,用三个引号括起来,同时向re.compile()中传入参数re.VERBOSE 告诉compile 忽略表达式中的空白符和注释。
import re
name_regex = re.compile(r'''
(\d{3}) #匹配三个数字
(.{3}) #匹配除换行符之外的任意内容三次
(\w{3}) #匹配三个字母
''',re.VERBOSE)
answer_1= name_regex.search('555w*whello world')
print(answer_1.group())
>>>
555w*whel
14、组合使用re.I 、re.DOTALL、re.VERBOSE
re.compile()只接受两个参数,如果希望在使用re.I忽略大小写时,同时让句点可以匹配换行符,或者可以在表达式中添加注释,可以用管道符将这些参数合并起来。
regex = re.compile(r'[a-z]',re.I|re.DOTALL|re.VERBOSE)
import re
name_regex = re.compile(r'''
([a-z]*) #匹配任意多个字母,不区分大小写
(\n) #匹配一个换行符
([0-9]*) # 匹配任意多个数字
''',re.I|re.DOTALL|re.VERBOSE)
answer_1= name_regex.search('abcdABCD\n8097809')
print(answer_1.group())
>>>
abcdABCD
8097809
python3.5学习笔记(第六章)的更多相关文章
- python3.4学习笔记(十六) windows下面安装easy_install和pip教程
python3.4学习笔记(十六) windows下面安装easy_install和pip教程 easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的 首先安 ...
- JVM学习笔记-第六章-类文件结构
JVM学习笔记-第六章-类文件结构 6.3 Class类文件的结构 本章中,笔者只是通俗地将任意一个有效的类或接口锁应当满足的格式称为"Class文件格式",实际上它完全不需要以磁 ...
- C Primer Plus 学习笔记 -- 前六章
记录自己学习C Primer Plus的学习笔记 第一章 C语言高效在于C语言通常是汇编语言才具有的微调控能力设计的一系列内部指令 C不是面向对象编程 编译器把源代码转化成中间代码,链接器把中间代码和 ...
- Linux学习笔记(第六章)
第六章-档案权限与目录配置#chgrp:改变档案的所属群组#chown:改变档案的拥有者#chmod:改变档案的权限及属性 chown用法 chmod用法: r:4 w:2 x:1对于文档: 对于目录 ...
- o'Reill的SVG精髓(第二版)学习笔记——第六章
第六章:坐标系统变换 想要旋转.缩放或者移动图片到新的位置.可以给对应的SVG元素添加transform属性. 6.1 translate变换 可以为<use>元素使用x和y属性,以在特性 ...
- 学习笔记 第六章 使用CSS美化图片
第六章 使用CSS美化图片 6.1 在网页中插入图片 GIF图像 跨平台能力,无兼容性问题: 具有减少颜色显示数目而极度压缩文件的能力,不会降低图像的品质(无损压缩): 支持背景透明功能,便于图像 ...
- [Python学习笔记][第六章Python面向对象程序设计]
1月29日学习内容 Python面向对象程序设计 类的定义与使用 类定义语法 使用class关键词 class Car: def infor(self): print("This is ca ...
- Java 学习笔记 ------第六章 继承与多态
本章学习目标: 了解继承的目的 了解继承与多态的关系 知道如何重新定义方法 认识java.lang.object 简介垃圾回收机制 一.继承 继承是java面向对象编程技术的一块基石,因为它允许创建分 ...
- 《Python基础教程(第二版)》学习笔记 -> 第六章 抽象
抽象和结构 本章将会介绍如何让将语句组织成函数,还会详细介绍参数(parameter)和作用域(scope)的概念,以及递归的概念及其在程序中的用途. 创建函数 函数可以调用,它执行某种行为,并返回某 ...
- Python3.6学习笔记(六)
WSGI Python Web Server Gateway Interface 规范学习 由于Python的灵活性,提供了多种方式可以作为服务端语言,包括Python编写的服务器(Medusa).P ...
随机推荐
- 如何线程调用C++类成员函数
方法就是: 1,写成静态成员函数 2,参数为 (void* __this)用来传入类 对象指针(this) 3,进入函数首先 C类名 *_this = (C类名*)__this; 转化为对象指 ...
- 网站运行编译器错误CS1617: 选项“6”对 /langversion 无效;必须是 ISO-1、ISO-2、3、4、5 或 Default
运行winform程序时提示, CS1617: 选项“6”对 /langversion 无效:必须是 ISO-1.ISO-2.3.4.5 或 Default 找到网站的web.config配置文件,找 ...
- Asp.Net MVC实现优酷(youku)Web的上传
优酷第三方上传API没有.NET版本的SDK,让从事.NET开发人员要实现开放平台上传文件无从下手.本文经过一天的预读优酷文档,以NET方式实现了视频上传. 参考: 优酷开放文档 http://ope ...
- SQLite的使用(包括编译安装的步骤)
SQLite官网http://www.sqlite.org/ SQLite简介 SQLite是一款轻型的数据库,是遵守ACID(原子性.一致性.隔离性和持久性)的关系式数据库管理系统.SQLite实现 ...
- QSocket 总体设计框架说明(观赏)
QSocket 是 QDAC 开源组件的一个重要的组成部分,终于要开始开工了,为了方便大家了解 QSocket,对 QSocket 的总体设计的一些想法,我在这里给大家简要的描述一下. 首先,QSoc ...
- delphi xe5 中TMemo控件的应用——for android
TMemo中的两个方法: TMemo.Lines.Add(stringxxx);意思是向TMemo中增加字符串stringxxx: TMemo.Lines.Text :=stringxxx,意思是清空 ...
- vi的替换使用、如何让linux有回收站功能、系统重要文件、目录数据
1 vi的替换使用方法 vi使用的原理 (编辑文件会生成一个隐藏临时文件) 1.1 替换文件内容方法:vi (1)%s#oldboy#oldgirl#g --- 将oldboy全部替换为oldgi ...
- spring boot 2.x 系列 —— actuator 服务监控与管理
文章目录 一.概念综述 1.1 端点 1.2 启用端点 1.3 暴露端点 1.4 健康检查信息 二.项目说明 1.1 项目结构说明 1.2 主要依赖 1.3 项目配置 1.4 查看监控状态 三.自定义 ...
- webpack打包工具的初级使用方法
这里下载的是webpack的3.8.1版本(新版更新的使用有些问题) 什么是webpack? 他是一个前端资源加载或打包工具,. 资源: img css json等. 下载的话 用 npm webpa ...
- oh-my-zsh自定义配置
oh-my-zsh主题配置 默认的zsh主题robbyrussell已经很棒了, 简洁高效, 能很好的显示git的相关信息, 比如branch信息, 修改, 删除, 添加等操作. 但是多用户的话就不能 ...