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

1.用 import re 导入正则表达式模块。
2.用 re.compile()函数创建一个 Regex 对象(记得使用原始字符串)。
3.向 Regex 对象的 search()方法传入想查找的字符串。它返回一个 Match 对象。
4.调用 Match 对象的 group()方法,返回实际匹配文本的字符串。

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

第1行:导入re模块
第2行:向 re.compile()传入一个字符串值,表示正则表达式,它将返回一个 Regex 模式对象,存储在变量phoneNumRegex中。(\d 表示“一个数字字符”,\d\d\d-\d\d\d-\d\d\d\d 是正确电话号码模式的正则表达式)
第3行:Regex 对象的 search()方法查找传入的字符串,寻找该正则表达式的所有匹配。如果字符串中没有找到该正则表达式模式,search()方法将返回None。如果找到了该模式, search()方法将返回一个Match对象。
第4行:Match 对象有一个group()方法,它返回被查找字 符串中实际匹配的文本。

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

1) 利用括号分组

添加括号将在正则表达式中创建“分组”: (\d\d\d)-(\d\d\d-\d\d\d\d)。然后可以使用 group()匹配对象方法,从一个分组中获取匹配的文本。

>>> import re
>>> phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)') 
>>> mo = phoneNumRegex.search('My number is 415-555-4242.') 
>>> mo.group(1) 
'415'
>>> mo.group(2) 
'555-4242' 
>>> mo.group(0) 
'415-555-4242' 
>>> mo.group() 
'415-555-4242' 
>>> mo.groups() 
('415', '555-4242') 
>>> areaCode, mainNumber = mo.groups() 
>>> print(areaCode) 
415 
>>> print(mainNumber) 
555-4242

括号在正则表达式中有特殊的含义,但是如果你需要在文本中匹配括号,在这种情况下,就需要用倒斜杠对‘(’和‘)’进行字符转义。

>>> 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’,且返回第一次出现的匹配文本。

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

也可以使用管道来匹配多个模式中的一个,作为正则表达式的一部分。例如,假设你希望匹配’Batman’、‘Batmobile’、'Batcopter’和’Batbat’中任意一个,同样地,返回的文本也是第一次匹配到的文本。

>>> batRegex = re.compile(r'Bat(man|mobile|copter|bat)') 
>>> mo = batRegex.search('Batmobile lost a wheel') 
>>> mo.group() 
'Batmobile' 
>>> mo.group(1) 
'mobile'

3)用问号实现可选匹配

正则表达式中的(###)?部分表明,模式 ### 是可选的分组。该正则表达式匹配的文本中,### 将出现零次或一次。

>>> phoneRegex = re.compile(r'(\d\d\d-)?\d\d\d-\d\d\d\d') 
>>> mo1 = phoneRegex.search('My number is 415-555-4242') 
>>> mo1.group() 
'415-555-4242' 
>>> mo2 = phoneRegex.search('My number is 555-4242') 
>>> mo2.group() 
'555-4242'

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

>>> batRegex = re.compile(r'Bat(wo)*man') 
>>> mo1 = batRegex.search('The Adventures 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('The Adventures 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)用花括号匹配特定次数

  • 如果想要一个分组重复特定次数,就在正则表达式中该分组的后面,跟上花括
    号包围的数字。例如,正则表达式(Ha){3}将匹配字符串’HaHaHa’,但不会匹配’HaHa’, 因为后者只重复了(Ha)分组两次。
  • 除了一个数字,还可以指定一个范围,即在花括号中写下一个最小值、一个逗号和一个最大值。例如,正则表达式(Ha){3,5}将匹配’HaHaHa’、‘HaHaHaHa’和’HaHaHaHaHa’。
  • 也可以不写花括号中的第一个或第二个数字,不限定最小值或最大值。例如,(Ha){3,}将匹配 3 次或更多次实例,(Ha){,5}将匹配 0 到 5 次实例。
6-1)贪心匹配与非贪心匹配

在字符串’HaHaHaHaHa’中,因为(Ha){3,5}可以匹配3个、4个或 5 个实例,你可能会想,为什么在前面花括号的例子中,Match 对象的 group()调用会返回’HaHaHaHaHa’, 而不是更短的可能结果。毕竟,'HaHaHa’和’HaHaHaHa’也能够有效地匹配正则表达 式(Ha){3,5}。 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' 

7)findall()方法

书上内容
注意,若像r’((##)($$)(%%%))'小分组外面还有一个大分组,则findall()返回的列表中的子元组的第一个元素是大分组的内容,即匹配的是整个正则表达式。

phoneNumRegex = re.compile(r'((\d\d\d)-(\d\d\d)-(\d\d\d\d))')
matches = phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
print(matches)
[('415-555-9999', '415', '555', '9999'), ('212-555-0000', '212', '555', '0000')]

作为 findall()方法的返回结果的总结,请记住下面两点:

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

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

8)不区分大小写的匹配

有时候你只关心匹配字母,不关心它们是大写或小写。要让正则表达式 不区分大小写,可以向 re.compile()传入 re.IGNORECASE 或 re.I,作为第二个参数。

9)用 sub()方法替换字符串

Regex 对象的 sub()方法需要传入两个参数。第一个参数是一个字符串,用于取代发现的匹配。第二个参数是一个字符串,即正则表达式。sub()方法返回替换完成后的字符串。


>>> namesRegex = re.compile(r'Agent \w+') 
>>> namesRegex.sub('CENSORED', 'Agent Alice gave the secret documents to Agent Bob.') 
'CENSORED gave the secret documents to CENSORED.' 

\d —— 0 到 9 的任何数字
\D —— 除 0 到 9 的数字以外的任何字符
\w —— 任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
\W —— 除字母、数字和下划线以外的任何字符
\s —— 空格、制表符或换行符(可以认为是匹配“空白”字符)
\S —— 除空格、制表符和换行符以外的任何字符

以上内容总结自《Python编程快速上手—让繁琐工作自动化》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值