Python中re模块的用法概览
模块re提供了对正则表达式的支持。
除标准文档外,Andrew Kuchling撰写的文章“Regular Expression HOWTO”(https://docs.python.org/3/howto/regex.html)也是很有用的Python正则表达式学习资料。
-
正则表达式是什么
正则表达式是可匹配文本片段的模式。最简单的正则表达式为普通字符串,与它自己匹配。换而言之,正则表达式'python'与字符串'python'匹配。你可使用这种匹配行为来完成如下工作:在文本中查找模式,将特定的模式替换为计算得到的值,以及将文本分割成片段。 -
通配符
正则表达式可与多个字符串匹配,你可使用特殊字符来创建这种正则表达式。例如,句点与除换行符外的其他字符都匹配,因此正则表达式'.ython'与字符串'python'和'jython'都匹配。它还与'qython'、'+ython'和' ython'(第一个字符为空格)等字符串匹配,但不与'cpython'、'ython'等字符串匹配,因为句点只与一个字符匹配,而不与零或两个字符匹配。
句点与除换行符外的任何字符都匹配,因此被称为通配符(wildcard)。 -
对特殊字符进行转义
普通字符只与自己匹配,但特殊字符的情况完全不同。例如,假设要匹配字符串'python.org',可以直接使用模式'python.org'吗?可以,但它也与'pythonzorg'匹配,这可能不是你想要的结果。要让特殊字符的行为与普通字符一样,可对其进行转义:像对字符串中的引号进行转义时所做的那样,在它前面加上一个反斜杠。因此,在这个示例中,可使用模式'python\.org',它只与'python.org'匹配。
请注意,为表示模块re要求的单个反斜杠,需要在字符串中书写两个反斜杠,让解释器对其进行转义。换而言之,这里包含两层转义:解释器执行的转义和模块re执行的转义。实际上,在有些情况下也可使用单个反斜杠,让解释器自动对其进行转义,但请不要这样依赖解释器。如果你厌烦了两个反斜杆,可使用原始字符串,如r'python.org'。 -
字符集
匹配任何字符很有用,但有时你需要更细致地控制。为此,可以用方括号将一个子串括起,创建一个所谓的字符集。这样的字符集与其包含的字符都匹配,例如'[pj]ython'与'python'和'jython'都匹配,但不与其他字符串匹配。你还可使用范围,例如'[a-z]'与a~z的任何字母都匹配。你还可组合多个访问,方法是依次列出它们,例如'[a-zA-Z0-9]'与大写字母、小写字母和数字都匹配。请注意,字符集只能匹配一个字符。要指定排除字符集,可在开头添加一个字符,例如'[abc]'与除a、b和c外的其他任何字符都匹配。
3.1 字符集中的特殊字符
一般而言,对于诸如句点、星号和问号等特殊字符,要在模式中将其用作字面字符而不是正则表达式运算符,必须使用反斜杠对其进行转义。在字符集中,通常无需对这些字符进行转义,但进行转义也是完全合法的。然而,你应牢记如下规则。
3.1.1 脱字符(^)位于字符集开头时,除非要将其用作排除运算符,否则必须对其进行转义。换而言之,除非有意为之,否则不要将其放在字符集开头。
3.1.2 同样,对于右方括号(])和连字符(-),要么将其放在字符集开头,要么使用反斜杠对其进行转义。实际上,如果你愿意,也可将连字符放在字符集末尾。 -
二选一和子模式
需要以不同的方式处理每个字符时,字符集很好,但如果只想匹配字符串'python'和'perl',该如何办呢?使用字符集或通配符无法指定这样的模式,而必须使用表示二选一的特殊字符:管道字符(|)。所需的模式为'python|perl'。然而,有时候你不想将二选一运算符用于整个模式,而只想将其用于模式的一部分。为此,可将这部分(子模式)放在圆括号内。对于前面的示例,可重写为'p(ython|erl)'。请注意,单个字符也可称为子模式。 -
可选模式和重复模式
通过在子模式后面加上问号,可将其指定为可选的,即可包含可不包含。例如,下面这个不太好懂的模式:
r'(http://)?(www.)?python.org'
只与下面这些字符串匹配:
'http://www.python.org'
'http://python.org'
'www.python.org'
'python.org'
对于这个示例,需要注意如下几点。
5.1 我对句点进行了转义,以防它充当通配符。
5.2 为减少所需的反斜杠数量,我使用了原始字符串。
5.3 每个可选的子模式都放在圆括号内。
5.4 每个可选的子模式都可以出现,也可以不出现。
问号表示可选的子模式可出现一次,也可不出现。还有其他几个运算符用于表示子模式可重复多次。
5.5 (pattern):pattern可重复0、1或多次。
5.6 (pattern)+:pattern可重复1或多次。
5.7 (pattern){m,n}:模式可重复m~n次。
例如,r'w.python.org'与'www.python.org'匹配,也与'.python.org'、'ww.python.org'和'wwwwwww.python.org'匹配。同样,r'w+.python.org'与'w.python.org'匹配,但与'.python.org'不匹配,而只与r'w{3,4}.python.org'与'www.python.org'和'wwww.python.org'匹配。
在这里,术语匹配指的是与整个字符串匹配,而函数match(参见表10-9)只要求模式与字符串开头匹配。 -
字符串的开头和末尾
到目前为止,讨论的都是模式是否与整个字符串匹配,但也可查找与模式匹配的子串,如字符串'www.python.org'中的子串'www'与模式'w+'匹配。像这样查找字符串时,有时在整个字符串开头或末尾查找很有用。例如,你可能想确定字符串的开头是否与模式'ht+p'匹配,为此可使用脱字符('')来指出这一点。例如,'ht+p'与'http://python.org'和'htttttp://python.org'匹配,但与'www.http.org'不匹配。同样,要指定字符串末尾,可使用美元符号($)。
完整的正则表达式运算符清单请参阅Python库中的Regular Expression Syntax部分。 -
模块re的内容
模块re包含多个使用正则表达式的函数,表10-9描述了其中最重要的一些。
模块re中一些重要的函数
|函数| 描述 |
| ---- | ---- |
|compile(pattern[, flags]) |根据包含正则表达式的字符串创建模式对象|
|search(pattern, string[, flags])| 在字符串中查找模式|
|match(pattern, string[, flags]) |在字符串开头匹配模式|
|split(pattern, string[, maxsplit=0]) |根据模式来分割字符串|
|findall(pattern, string) |返回一个列表,其中包含字符串中所有与模式匹配的子串|
|sub(pat, repl, string[, count=0]) |将字符串中与模式pat匹配的子串都替换为repl|
|escape(string)| 对字符串中所有的正则表达式特殊字符都进行转义|
函数re.compile将用字符串表示的正则表达式转换为模式对象,以提高匹配效率。调用search、match等函数时,如果提供的是用字符串表示的正则表达式,都必须在内部将它们转换为模式对象。通过使用函数compile对正则表达式进行转换后,每次使用它时都无需再进行转换。
模式对象也有搜索/匹配方法,因此re.search(pat, string)(其中pat是一个使用字符串表示的正则表达式)等价pat.search(string)(其中pat是使用compile创建的模式对象)。编译后的正则表达式对象也可用于模块re中的普通函数中。函数re.search在给定字符串中查找第一个与指定正则表达式匹配的子串。如果找到这样的子串,将返回MatchObject(结果为真),否则返回None(结果为假)。鉴于返回值的这种特征,可在条件语句中使用这个函数,如下所示:
if re.search(pat, string):
print('Found it!')
然而,如果你需要获悉有关匹配的子串的详细信息,可查看返回的MatchObject。下一节将更详细地介绍MatchObject。
函数re.match尝试在给定字符串开头查找与正则表达式匹配的子串,因此re.match('p','python')返回真(MatchObject),而re.match('p', 'www.python.org')返回假(None)。
函数match在模式与字符串开头匹配时就返回True,而不要求模式与整个字符串匹配。如果要求与整个字符串匹配,需要在模式末尾加上一个美元符号。美元符号要求与字符串末尾匹配,从而将匹配检查延伸到整个字符串。
函数re.split根据与模式匹配的子串来分割字符串。这类似于字符串方法split,但使用正则表达式来指定分隔符,而不是指定固定的分隔符。例如,使用字符串方法split时,可以字符串', '为分隔符来分割字符串,但使用re. split时,可以空格和逗号为分隔符来分割字符串。
some_text = 'alpha, beta,,,,gamma delta'
re.split('[, ]+', some_text)
['alpha', 'beta', 'gamma', 'delta']
如果模式包含圆括号,将在分割得到的子串之间插入括号中的内容。例如,re.split('o(o)','foobar')的结果为['f', 'o', 'bar']。
从这个示例可知,返回值为子串列表。参数maxsplit指定最多分割多少次。
re.split('[, ]+', some_text, maxsplit=2)
['alpha', 'beta', 'gamma delta']
re.split('[, ]+', some_text, maxsplit=1)
['alpha', 'beta,,,,gamma delta']
函数re.findall返回一个列表,其中包含所有与给定模式匹配的子串。例如,要找出字符串包含的所有单词,可像下面这样做:
pat = '[a-zA-Z]+'
text = '"Hm... Err -- are you sure?" he said, sounding insecure.'
re.findall(pat, text)
['Hm', 'Err', 'are', 'you', 'sure', 'he', 'said', 'sounding', 'insecure']
要查找所有的标点符号,可像下面这样做:
pat = r'[.?-",]+'
re.findall(pat, text)
['"', '...', '--', '?"', ',', '.']
请注意,这里对连字符(-)进行了转义,因此Python不会认为它是用来指定字符范围的(如a-z)。
函数re.sub从左往右将与模式匹配的子串替换为指定内容。请看下面的示例:
pat = '{name}'
text = 'Dear {name}...'
re.sub(pat, 'Mr. Gumby', text)
'Dear Mr. Gumby...'
有关如何更有效地使用这个函数,请参阅随后的一节。
re.escape是一个工具函数,用于对字符串中所有可能被视为正则表达式运算符的字符进行转义。使用这个函数的情况有:字符串很长,其中包含大量特殊字符,而你不想输入大量的反斜杠;你从用户那里获取了一个字符串(例如,通过函数input),想将其用于正则表达式中。下面的示例说明了这个函数的工作原理:
re.escape('www.python.org')
'www\.python\.org'
re.escape('But where is the ambiguity?')
'But\ where\ is\ the\ ambiguity\?'
在表10-9中,注意到有些函数接受一个名为flags的可选参数。这个参数可用于修改正则表达式的解读方式。有关这方面的详细信息,请参阅“Python库参考手册”中讨论模块re的部分。
浙公网安备 33010602011771号