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编程快速上手—让繁琐工作自动化》