正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
操作步骤
虽然在 Python 中使用正则表达式有几个步骤,但每一步都相当简单。
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
此处的r表示该字符串是原始字符串’'也被认为是非转义字符
分组
正则表达式字符串中的第一对括号是第 1 组。第二对括号是第 2 组。向 group() 匹配对象方法传入整数 1 或 2,就可以取得匹配文本的不同部分。向 group()方法传 入 0 或不传入参数,将返回整个匹配的文本。
示例
phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)')
mo = phoneNumRegex.search('My number is 415-555-4242.')
print(mo.group(0)) #415-555-4242
print(mo.group(1)) #415
print(mo.group(2)) #555-4242
管道
字符 | 称为管道,表示或,即匹配二者之一
正则表达式 r’Batman|Tina Fey’将匹配’Batman’或’Tina Fey’
问号
?(问号)表明它前面的分组在这个模式中是可选的。不论这段文本在不在,正则表达式 都会认为匹配。(该段出现一次或零次)
示例
batRegex = re.compile(r'Bat(wo)?man')
mo1 = batRegex.search('The Adventures of Batman')
mo1.group()
加号
+(加号)意味着“匹配一次或多次。
示例
batRegex = re.compile(r'Bat(wo)+man')
mo1 = batRegex.search('The Adventures of Batwowoman')
mo1.group()
星号
*(称为星号)意味着“匹配零次或多次。
示例
batRegex = re.compile(r'Bat(wo)+man')
mo0 = batRegex.search('The Adventures of Batman')
mo0.group()
mo1 = batRegex.search('The Adventures of Batwowoman')
mo1.group()
花括号
若要让一个分组重复特定的次数,可以在分组后加上大括号,括号内加上需要重复的次数。
此外,括号内还可写一个范围,用逗号分隔,表示重复的次数在这个范围内
示例
(Ha){3} 只能匹配(Ha)(Ha)(Ha)
(Ha){3,5} 可以匹配((Ha)(Ha)(Ha))|((Ha)(Ha)(Ha)(Ha))|((Ha)(Ha)(Ha)(Ha)(Ha))
正则表达式的匹配默认是贪心的
即如果可以匹配更长的字符串,不会匹配短的那个
例如(Ha){3,5} 中若式子为HaHaHaHaHa,将会匹配HaHaHaHaHa而不是HaHaHa。
若要匹配最短的字符串,应当在花括号之后加一个?,表示非贪心匹配。
findall()方法
search()方法只会匹配第一次出现的合法字符串,而findall()方法将会返回所有的匹配字符串。
作为 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’)]。
特殊符号
\d 0 到 9 的任何数字
\D 除 0 到 9 的数字以外的任何字符
\w 任何字母、数字或下划线字符(可以认为是匹配“单词”字符)
\W 除字母、数字和下划线以外的任何字符
\s 空格、制表符或换行符(可以认为是匹配“空白”字符)
\S 除空格、制表符和换行符以外的任何字符
自定义匹配集合
示例
vowelRegex = re.compile(r'[aeiouAEIOU]')
vowelRegex.findall('RoboCop eats baby food. BABY FOOD.')
也可以使用短横表示字母或数字的范围。例如,字符分类[a-zA-Z0-9]将匹配所 有小写字母、大写字母和数字。
通过在字符分类的左方括号后加上一个插入字符(^), 就可以得到“非字符类” 。 非字符类将匹配不在这个字符类中的所有字符。
示例
consonantRegex = re.compile(r'[^aeiouAEIOU]')
consonantRegex.findall('RoboCop eats baby food. BABY FOOD.')
前匹配与后匹配
可以在正则表达式的开始处使用插入符号(^),表明匹配必须发生在被查找文本开始处。
类似地,可以在正则表达式的末尾加上美元符号($),表示该字符串必须以这个正则表达式的模式结束
示例
#匹配以Hello开头的字符串
beginsWithHello = re.compile(r'^Hello')
beginsWithHello.search('Hello world!')
#匹配以0-9结束的字符串
endsWithNumber = re.compile(r'\d$')
endsWithNumber.search('Your number is 42')
通配符
在正则表达式中,.(句点)字符称为“通配符”。它匹配除了换行之外的所有字符。
但应注意的是:句点字符只能匹配一个字符
若要匹配任意个字符,可使用 . *(句点加星号)
示例
#匹配 <To serve man> for dinner.>
greedyRegex = re.compile(r'<.*>')
mo = greedyRegex.search('<To serve man> for dinner.>')
mo.group()
点-星使用“贪心”模式:它总是匹配尽可能多的文本。要用“非贪心”模式匹配所有文本,就使用点-星和问号
示例
#匹配 <To serve man>
greedyRegex = re.compile(r'<.*?>')
mo = greedyRegex.search('<To serve man> for dinner.>')
mo.group()
此外,尤其值得注意的是:
点-星只能匹配除换行符外的字符串
若要匹配所有字符,通过传入 re.DOTALL 作为 re.compile()的第 二个参数,可以让句点字符匹配所有字符,包括换行字符。
不区分大小写的匹配
要让正则表达式 不区分大小写,可以向 re.compile()传入 re.IGNORECASE 或 re.I,作为第二个参数。
使用sub()方法替换字符串
使用前一个参数字符串替代后一个字符串中所有符合指定正则式的部分
示例
namesRegex = re.compile(r'Agent \w+')
print( namesRegex.sub('CENSORED', 'Agent Alice gave the secret documents to Agent Bob.') )
#将打印CENSORED gave the secret documents to CENSORED.
参数组合
如果希望正则表达式不区分大小写,并且句点字符匹配换行,就可以这 样构造 re.compile()调用:
someRegexValue = re.compile('foo', re.IGNORECASE | re.DOTALL)
管理复杂的正则表达式
如果要匹配的文本模式很简单,正则表达式就很好。但匹配复杂的文本模式, 可能需要长的、费解的正则表达式。你可以告诉 re.compile(),忽略正则表达式字符 串中的空白符和注释,从而缓解这一点。要实现这种详细模式,可以向 re.compile() 传入变量 re.VERBOSE,作为第二个参数。
示例
前后```表示这是一个多行字符串 ,参数re.VERBOSE会忽略其中的注释与空白符
phoneRegex = re.compile(r'''(
(\d{3}|\(\d{3}\))? # area code
(\s|-|\.)? # separator
(\d{3}) # first 3 digits
(\s|-|\.) # separator
(\d{4}) # last 4 digits
(\s*(ext|x|ext.)\s*(\d{2,5}))? # extension
)''', re.VERBOSE)