re 模块是 python 标准库的一部分,它对正则表达式(regular expression)提供了支持。本文部分内容参考自《Beginning Python From Novice to Professional Second Edition》和 python 官方文档(https://docs.python.org/3/)
在测试前请导入 re 模块:
import re
函数 | 描述 |
---|---|
split(pattern, string[, flags]) | 根据模式的匹配项来分割字符串 |
findall(pattern, string) | 列出字符串中模式的所有匹配项 |
sub(pat, repl, string[, count=0]) | 将字符串中所有pat的匹配项用repl替换 |
escape(string) | 将字符串中的所有特殊正则表达式字符转义 |
match(pattern, string[, flags]) | 在字符串的开始处匹配模式 |
下面分别举例说明:
函数 split() 会根据模式的匹配项来分割字符串。第一个参数是要匹配的模式,第二个参数是目标字符串,第三个参数是可选标志,例如用逗号或空格以及他们的组合来分割字符串,加号表示允许重复一次或者多次,方括号中的逗号和空格表示字符集:
>>> s = 'very, good,,,,,I ,love you'
>>> re.split('[, ]+', s)
['very', 'good', 'I', 'love', 'you']
该函数的 maxsplit 可选标志表示字符串最多可以被分割几次(注意结果列表中黑色逗号的个数):
>>> s = 'very, good,,,,,I ,love you'
>>> re.split('[, ]+', s, maxsplit = 3)
['very', 'good', 'I', 'love you']
>>> re.split('[, ]+', s, maxsplit = 2)
['very', 'good', 'I ,love you']
>>> re.split('[, ]+', s, maxsplit = 1)
['very', 'good,,,,,I ,love you']
函数 findall() 会以列表的形式返回给定模式的所有匹配项。比如要在字符串中查找所有的单词:
>>> pat = '[a-zA-Z]+'
>>> s = '"Oh, I think you should do it. Will you?" she said, sounding nervously'
>>> re.findall(pat, s)
['Oh', 'I', 'think', 'you', 'should', 'do', 'it', 'Will', 'you', 'she', 'said', 'sounding', 'vervously']
或者你也可以查找标点符号:
>>> pat = '[.?",]+'
>>> re.findall(pat, s)
['"', ',', '.', '?"', ',']
如上所示,找到了:双引号,逗号,句号,问号和双引号的组合,逗号
函数 sub() 会将字符串 string 中的所有 pat 替换位 repl。
例如批量替换:
>>> s = 'I was wrong. I fell very sorry! I want to apologize'
>>> pat = 'I'
>>> re.sub(pat, 'you', s)
'you was wrong. you fell very sorry! you want to apologize'
函数 escape() 会将字符串 string 中的所有特殊正则表达式字符转义。它可以对字符串中所有可能被解释为正则运算符的字符进行转义。如果字符串很长且包含很多特殊字符,而你又不想输入一大堆反斜杠,又或者字符串是由用户输入的,并且会被用于正则表达式的一部分的时候,可以使用这个函数。
例如(这个例子来自于《python基础教程 第2版 修订版》):
>>> re.escape('www.python.org')
'www\\.python\\.org'
>>> re.escape('But where is the ambiguity?')
'But\\ where\\ is\\ the\\ ambiguity\\?'
函数 match() 可以在字符串的开始处进行匹配,会返回一个匹配对象(其实内容即是一个匹配的字符串)。
不过我们先来看看匹配对象和组,对于 re 模块中的那些能够对字符串进行模式匹配的函数而言,当能够找到匹配项的时候,它们都会返回 MatchObject 对象。这些对象包括匹配模式的子字符串的信息。它们还包含了“哪个模式匹配子字符串哪部分的信息”——这些“部分”叫做组(group)。
简而言之,组就是放置在圆括号内的子模式。组的序号取决于它左侧的括号数。组0就是整个模式,例如下面这个模式中:
'There (was a (wee) (cooper)) who (lived in Fyfe)'
包含下面这些组:
组0: There was a wee cooper who lived in Fyfe
组1: was a wee cooper
组2: wee
组3: cooper
组4: lived in Fyfe
假如我们对以 .com 结尾的域名比较感兴趣,那么下面的模式正好满足我们的要求(模式前面加上小写字母r表示防止转义,例如 (\.)会转义为通配符(.),则在模式中要表示一般的符号(.),则必须用两个反斜杠(\\.)):
r'www\.(.+)\.com$'
我们通过上面的模式匹配得到一个匹配对象,就可以调用匹配对象的如下几个方法来获得我们想要的内容:
方法 | 描述 |
---|---|
group([group1,…]) | 获取给定子模式(组)的匹配项 |
start([group]) | 返回给定组的匹配项的开始位置,无参数时返回0,即整个模式 |
end([group]) | 返回给定组的匹配项的结束位置(结束位置是匹配项最后一个字符的下一个位置),无参数时返回整个模式最后一个字符的索引加1 |
span([group]) | 返回一个组的开始位置和结束位置,无参数时返回一个整个模式的开始位置和结束位置 |
例如下面的例子:
>>> pat = r'www\.(.*)\..{3}'
>>> s = 'www.python.org'
>>> re.match(pat, s)
<_sre.SRE_Match object; span=(0, 14), match='www.python.org'> # 此处返回了一个对象
>>> m = re.match(pat, s)
>>> m.group(1)
'python'
>>> m.start(1)
4
>>> m.end(1)
10
>>> m.span(1)
(4, 10)
还有一个例子,假如我们想把 ‘*Somthing*’ 用 ‘somthing’ 替换掉。前者是普通文本,而后者是 html 代码。首先应该建立正则表达式:
>>> em_pat = r'\*([^\*]+)\*'
现在我们就可以用函数 re.sub() 进行替换了,sub() 函数有一个强大的功能就是如果在替换内容中出现 ‘\\n’ (或者 r’\n’ )形式的转义序列,那么该转义序列会被匹配到的字符串中组 n 的内容替换掉:
>>> s = 'hello, *world*!'
>>> repl = r'\1'
>>> re.sub(em_pat, repl, s)
'hello, world!'