《Python 编程快速上手 — 让繁琐工作自动化》读书笔记之【第7章 模式匹配与正则表达式(1)】

本文介绍了如何使用Python的正则表达式进行文本模式查找,包括基本语法、分组、匹配选项等,并通过实例展示了findall方法的应用。

1.  用正则表达式查找文本模式

正则表达式,简称为 regex,是文本模式的描述方法。

1)  创建regex对象

Python中所有正则表达式的函都在re模块中,如果在使用时没有导入则会报错。向re.compile()传入一个正在表达式,它将返回一个Regex模式对象(或简称Regex对象)。

示例:

>>>phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')

2)  匹配 Regex 对象

Regex 对象的search()方法查找传入的字符串,寻找该正则表达式的所有匹配。如果字符串中没有找到该正则表达式模式,search()方法将返回None。如果找到了该模式,search()方法将返回一个 Match 对象。Match 对象有一个 group()方法,它返回被查找字符串中实际匹配的文本。示例:

>>>phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
>>> mo = phoneNumRegex.search('My number is 415-555-4242.')
>>> print('Phonenumber found: ' + mo.group())
Phone number found: 415-555-4242

2.  用正则表达式匹配更多模式

1)  利用括号分组

使用括号可以在正则表达式中创建分组,然后使用group()方法,就可以从一个分组中获得匹配的文本。正则表达式字符串中的第一对括号是第1 组,第二对括号是第 2 组,以此类推。向 group()方法传入整数 1 或 2……,就可以取得匹配文本的不同部分。向 group()方法传入 0 或不传入参数,将返回整个匹配的文本。如果想要一次就获取所有的分组,请使用groups()方法。示例:

>>>phoneNumRegex = re.compile(r'(\(\d\d\d\))(\d\d\d-\d\d\d\d)')
>>> mo = phoneNumRegex.search('My phone number is (415) 555-4242.')
>>> mo.group(1)
'(415)'
>>> mo.group(2)
'555-4242'

2)  用管道匹配多个分组

字符|称为“管道”。希望匹配许多表达式中的一个时,就可以使用它。例如,正则表达式 r'Batman|Tina Fey'将匹配'Batman'或'Tina Fey'

如果 Batman 和 Tina Fey 都出现在被查找的字符串中,第一次出现的匹配文本,将作为 Match 对象返回。

如果需要匹配真正的管道字符,就用倒斜杠转义,即\|。

示例:

>>>heroRegex = re.compile (r'Batman|TinaFey')
>>> mo1 = heroRegex.search('Batman and Tina Fey.')
>>> mo1.group()
'Batman'
>>> mo2 = heroRegex.search('Tina Fey and Batman.')
>>> mo2.group()
'Tina Fey'

3)  用问号实现可选匹配

字符?表明它前面的分组在这个模式中是可选的。示例:

>>> batRegex= re.compile(r'Bat(wo)?man')
>>> mo1 = batRegex.search('TheAdventures of Batman')
>>> mo1.group()
'Batman'
>>> mo2 = batRegex.search('The Adventures of Batwoman')
>>> mo2.group()
'Batwoman'

4)  用星号匹配零次或多次

*(称为星号)意味着“匹配零次或多次”,即星号之前的分组,可以在文本中出现任意次。示例:

>>> batRegex= re.compile(r'Bat(wo)*man')
>>> mo1 = batRegex.search('TheAdventures of Batman')
>>> mo1.group()
'Batman'
>>> mo2 = batRegex.search('The Adventures of Batwoman')
>>> mo2.group()
'Batwoman'
>>> mo3 = batRegex.search('The Adventures of Batwowowowoman')
>>> mo3.group()
'Batwowowowoman'

5)  用加号匹配一次或多次

*意味着“匹配零次或多次”,+(加号)则意味着“匹配一次或多次”。如果需要匹配真正的加号字符,在加号前面加上倒斜杠实现转义:\+。示例:

>>> batRegex= re.compile(r'Bat(wo)+man')
>>> mo1 = batRegex.search('TheAdventures of Batwoman')
>>> mo1.group()
'Batwoman'
>>> mo2 = batRegex.search('The Adventures of Batwowowowoman')
>>> mo2.group()
'Batwowowowoman'
>>> mo3 = batRegex.search('The Adventures of Batman')
>>> mo3 == None
True

6)  用花括号匹配特定次数

如果想要一个分组重复特定次数,就在正则表达式中该分组的后面,跟上花括号包围的数字。

a)     如果只有一个数字n,表示出现n次。例如,正则表达式(Ha){3}将匹配字符串'HaHaHa',

b)     还可以指定一个范围,即在花括号中写下一个最小值、一个逗号和一个最大值。例如,正则表达式(Ha){3,5}将匹配'HaHaHa'、'HaHaHaHa'和'HaHaHaHaHa'。

c)     指定范围时,如果省略第一个值,表示从0开始,如果省略第二个值,表示不限定。

示例:

>>> haRegex= re.compile(r'(Ha){3}')
>>> mo1 = haRegex.search('HaHaHa')
>>> mo1.group()
'HaHaHa'
>>> mo2 = haRegex.search('Ha')
>>> mo2 == None
True

3.  贪心和非贪心匹配

Python 的正则表达式默认是“贪心”的,这表示在有二义的情况下,它们会尽可能匹配最长的字符串。花括号的“非贪心”版本匹配尽可能最短的字符串,即在结束的花括号后跟着一个问号。示例:

>>>greedyHaRegex = re.compile(r'(Ha){3,5}')
>>> mo1 = greedyHaRegex.search('HaHaHaHaHa')
>>> mo1.group()
'HaHaHaHaHa'
>>> nongreedyHaRegex =re.compile(r'(Ha){3,5}?')
>>> mo2 = nongreedyHaRegex.search('HaHaHaHaHa')
>>> mo2.group()
'HaHaHa'

4.  findall()方法

Regex对象有一个findall()方法。作为 findall()方法的返回结果的总结,请记住下面两点:

如果调用在一个没有分组的正则表达式上,例如\d\d\d-\d\d\d-\d\d\d\d,方法findall()将返回一个匹配字符串的列表,例如['415-555-9999', '212-555-0000']。示例;

>>> phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') # has no groups
>>> phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
['415-555-9999', '212-555-0000']

如果调用在一个有分组的正则表达式上,例如(\d\d\d)-(\d\d\d)-(\d\d\d\d),方法 findall()将返回一个字符串的元组的列表(每个分组对应一个字符串),例如[('415','555', '1122'), ('212', '555', '0000')]。示例:

>>> phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)') # has groups
>>> phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
[('415', '555', '1122'), ('212', '555', '0000')]

5.  字符分类

6.  建立自己的字符分类

可以用方括号自定义字符分类,示例;

>>> vowelRegex = re.compile(r'[aeiouAEIOU]')
>>> vowelRegex.findall('RoboCop eats baby food. BABY FOOD.')
['o', 'o', 'o', 'e', 'a', 'a', 'o', 'o', 'A', 'O', 'O']


也可以使用短横表示字母或数字的范围。例如,字符分类[a-zA-Z0-9]将匹配所有小写字母、大写字母和数字。

在方括号内,普通的正则表达式符号不会被解释。这意味着,你不需要前面加上倒斜杠转义.、*、?或()字符。例如,字符分类将匹配数字 0 到 5 和一个句点。你不需要将它写成[0-5\.]。

通过在字符分类的左方括号后加上一个插入字符(^),就可以得到“非字符类”。非字符类将匹配不在这个字符类中的所有字符。

7.  插入字符和美元字符

^表明匹配必须发生在被查找文本开始处。$表示该字符串必须以这个正则表达式的模式结束。可以同时使用^和$,表明整个字符串必须匹配该模式。示例:

>>> wholeStringIsNum = re.compile(r'^\d+$')
>>> wholeStringIsNum.search('1234567890')
<_sre.SRE_Match object; span=(0, 10), match='1234567890'>
>>> wholeStringIsNum.search('12345xyz67890') == None
True
>>> wholeStringIsNum.search('12 34567890') == None
True


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值