正则表达式(Regex)用于文本匹配,可以大量减少代码编写量。
基本步骤
- 模块导入
python运用正则表达式首先要导入re
模块。
import re
- 创建对象
再向re.compile()
传入字符串表示正则表达式,返回Regex对象,如
phoneNum = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
字符串前加
r
表示原始字符串,以免\d
被识别为转移字符。
- 搜索
Regex对象search()
方法查找传入的字符串,寻找该正则表达式的所有匹配。如果没有找到,则返回None
;如果找到了,则返回Match
对象。如
mo = phoneNum.search('My number is 415-555-1234.')
print('Phone number found: ' + mo.group())
其中的group()
方法将在下文讲述。
- 匹配
还可使用match()
函数对字符串进行匹配,如
phoneNum.match('415-555-1234.')
综上,我们将希望的模式传递给re.compile()
,并得到Regex对象。再用search()
方法传入想查找的字符串,并将结果保存在mo
中。或者使用match()
方法进行匹配。match()
是进行完全匹配,而search()
是进行搜索,无需完全匹配。
例子
括号分组
在上面的代码中用到了group()
方法,它可配合括号()
进行分组,如
phoneNum = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)')
mo = phoneNum.search('My number is 415-555-1234.')
print(mo.group()) # '415-555-1234'
print(mo.group(0)) # '415-555-1234'
print(mo.group(1)) # '415'
print(mo.group(2)) # '555-1234'
其中,传入参数1和2分别代表第1个和第2个括号的匹配,如果是0或空则表示整个匹配。
要想一次性获得所有分组则使用groups()
方法(注意单复数),如
print(mo.groups()) # ('415', '555-1234')
括号在正则表达式中有特殊含义,如果需要匹配括号,则需要使用转义字符。
管道分组
要想匹配许多表达式中的1个时就可以使用管道|
,如
name = re.compile(r'Alice|Bob')
mo1 = name.search('My name is Alice')
print(mo1.group()) # Alice
mo2 = name.search('My name is Bob')
print(mo2.group()) # Bob
mo3 = name.search('Alice and Bob')
print(mo3.group()) # Alice
这里正则表达式将匹配Alice或Bob,如果两个都有,则匹配第一次出现的。如果需要返回所有匹配,则使用findall()
方法,在下一节中讲述。
同理,正则表达式若需要匹配
|
,则应当用转义字符。
findall()
方法
findall()
方法返回查找字符串的所有匹配,返回的不是Match
对象,而是字符串列表。只要没有分组,列表中的每个字符串都是一段被查找文本,如
phoneNum = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
phoneNum.findall('Cell: 123-456-7890 Work: 987-654-3210')
# ['123-456-7890', '987-654-3210']
如果有分组,则返回元组列表,如
phoneNum = re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)')
phoneNum.findall('Cell: 123-456-7890 Work: 987-654-3210')
# [('123', '456', '7890'), ('987', '654', '3210')]
匹配换行
在正则表达式中,句点.
称为通配符,它匹配除了换行外的所有字符,如
noLine = re.compile('.*')
noLine.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
# 输出'Serve the public trust.'
这里只匹配到了第1个换行符之前的内容。如果需要通配符.
可以匹配换行符,则需要将re.DOTALL
作为re.compile()
的第2个参数,如
newLine = re.compile('.*', re.DOTALL)
newLine.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
# 输出'Serve the public trust.\nProtect the innocent.\nUphold the law.'
这就匹配了包含换行符在内的所有字符。
大小写
如果不关心大小写可以向re.compile()
传入re.IGNORECASE
或re.I
作为第2个参数,如
robot = re.compile(r'robot', re.I)
robot.search('Robot is AI').group() # 'Robot'
robot.search('ROBOT is AI').group() # 'ROBOT'
替换
正则表达式不仅能找到文本模式,并且可以用新文本进行替换。Regex对象的sub()
方法可以完成这项工作,其第1个参数是字符串,用于取代发现的匹配;第2个参数是字符串,用于匹配内容。该方法返回替换后的字符串。如
nameSub = re.compile(r'Alice')
nameSub.sub('Bob', 'My name is Alice')
# 输出'My name is Bob'
匹配字符串中的Alice被Bob取代了。
空白
有时候正则表达式很长很复杂,如果需要忽略正则表达式中的空格和注释需要把re.VERBOSE
作为第2个参数传递给re.compile()
。这样一来,复杂的正则表达式可以写成多行,甚至可以加上注释。