0. 前言
发现自己在使用python的正则模块的时候,经常忘记具体的使用方法,搜索的话很快能得到解答,但过不了一阵就又忘记,而官方API文档有时候查找也是个麻烦。所以也就写个备忘,按照用途来归纳一下网上有的一些使用RE模块的经验。注意,本篇不讲述基本概念。
首先当然是要
import re
1. 用法
1.1 先compile后match
适用于模式需要多次使用
p = re.compile('ab*')# p:re.RegexObject
p.match("abbbb")#将返回一个 MatchObject
compile方法可以接受一些标志常量作为第二个参数,例如re.IGNORECASE
返回的MatchObject
可以做进一步操作:
方法/属性 | 作用 |
---|---|
group() | 返回被 RE 匹配的字符串 |
start() | 返回匹配开始的位置 |
end() | 返回匹配结束的位置 |
span() | 返回一个元组包含匹配 (开始,结束) 的位置 |
具体效果用一次就知道。
1.2 直接匹配
如果模式不需要多次使用,直接匹配即可:
re.match(patternString, text)#返回的是MatchObject
这些模块级函数的基本用法与RegexObject几乎一致,只是需要传入一个pattern参数,不再赘述。
1.3 match与search
只有在字符串的开头开始匹配,match才会返回MatchObject对象,而search则在全text中寻找匹配。例如
line = "Cats are smarter than dogs";
#No match!!
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
print "match --> matchObj.group() : ", matchObj.group()
else:
print "No match!!"# if line="dogs are smarter than cats", things change
#search --> matchObj.group() : dogs
searchObj = re.search( r'dogs', line, re.M|re.I)
if searchObj:
print "search --> searchObj.group() : ", searchObj.group()
else:
print "Nothing found!!"
1.4 特殊符号
特殊符号主要是.
,\
,$
,^
等具有特殊意义的符号,这些符号的一般用法我不予介绍,在第2节的规则图中都有说明,本小节只介绍特殊用法。
'\'
反斜杠在正则表达式中用于转义。同时注意,在python的字符串中反斜杠同样用于转义,所以反斜杠会经过两层解释:python字符串解释,正则表达式解释。
这可能导致一些意料之外的问题,例如想在Latex文本中匹配\section
,它作为RE表达式,需要写成'\\section'
转义反斜杠,同时,如果它直接作为字符串参数传入RE模块,则还要分别对这两个反斜杠转义,写成'\\\\section'
,显然这不漂亮。
一种便捷的方式是使用raw字符,这可以免去字符串转义,写成r'\\section'
。但是注意,这时候所有字符串中的特殊转义就无用了,r'\n'
将被识别为一个'\'
和一个'n'
。
另一种就是老老实实用compile。
'.'
点号,如果指定了 DOTALL
标记,匹配包括换行符在内的任意一个字符。
'^'
尖号,在MULTILINE
模式下,将匹配任意一个新行的开始。
'$'
dollar符号,匹配一个字符串的结尾或者字符串最后面的换行符,在MULTILINE
模式下,匹配任意一行的行尾。也就是说,普通模式下,foo.$
去搜索'foo1\nfoo2\n'
只会找到'foo2'
,但是在 MULTILINE
模式,还能找到 'foo1'
,而且就用一个 $
去搜索'foo\n'
的话,会找到两个空的匹配:一个是最后的换行符,一个是字符串的结尾,演示:
>>> re.findall('(foo.$)', 'foo1\nfoo2\n')
['foo2']
>>> re.findall('(foo.$)', 'foo1\nfoo2\n', re.MULTILINE)
['foo1', 'foo2']
>>> re.findall('($)', 'foo\n')
['', '']
*?
, +?
, ??
'*'
,'+'
和'?'
都是贪婪的,但这也许并不是我们所要的。可以在后面加个问号,将策略改为非贪婪,只匹配尽量短的RE。示例,体会两者的区别:
>>> re.findall('<(.*)>', '<H1>title</H1>')
['H1>title</H1']
>>> re.findall('<(.*?)>', '<H1>title</H1>')
['H1', '/H1']
{m,n}?
{m,n},也是贪婪的,a{3,5}如果有5个以上连续a的话,会匹配5个,这个也可以通过加问号改变。a{3,5}?如果可能的话,将只匹配3个a。
(?…)
这是一个表达式的扩展符号。’?’后的第一个字母决定了整个表达式的语法和含义,除了(?P…)以外,表达式不会产生一个新的组。如果需要指定匹配模式或者需要对匹配起别名以便提取,可以使用这个符号。
\b
匹配单词边界(包括开始和结束),这里的“单词”,是指连续的字母、数字和下划线组成的字符串。注意,\b的定义是\w和\W的交界,所以精确的定义有赖于UNICODE和LOCALE这两个标志位。
\B
和\b相反,\B匹配非单词边界。 \b
和\B
是零宽界定符(zero-width assertions)
前向界定符(lookahead assertion)
前向界定符也是一种零宽界定符(zero-width assertion)。前向界定符包括前向肯定界定符和前向否定界定符,如下所示: (?=...)
前向肯定界定符。如果所含正则表达式(以 ...
表示)在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎并不会停止,模式的剩余部分还要尝试匹配界定符的右边。 (?!...)
前向否定界定符。与肯定界定符相反,当所含表达式不能在字符串当前位置匹配时成功,模式的剩余部分继续参与匹配。
文字描述可能不太好理解,看例子
要求匹配所有文件扩展名不为bat的文件,包括.ba,.batch等。
.*[.](?!bat$).*$
使用了前向否定界定,当bat$
匹配失败时,当前位置不移动,继续匹配后面的表达式,当bat$
匹配成功时,当前位置失败,停止匹配并返回。
前向否定的意思:在当前位置向前看(前向),如果表达式 bat$
不会被匹配,尝试模式的其余部分(当做没有这个表达式,当前位置不变);如果 bat$
匹配,整个模式将失败(否定)。后面的 $
是为了确保象 “sample.batch” 这样以 “bat” 开头的扩展名会被允许。
2. 正则表达式的规则
一图胜千言
3. 字符串操作
RegexObject提供一些方法来对字符串进行操作。
方法/属性 | 作用 |
---|---|
split(string [, maxsplit = 0]) | 将字符串在 RE 匹配的地方分片并生成一个列表 |
sub(replacement, string[, count = 0]) | 找到 RE 匹配的所有子串,并将其用一个不同的字符串替换 |
subn(replacement, string[, count = 0]) | 与 sub() 相同,但返回新的字符串和替换次数 |
replacement
中可以使用逆向引用,与正则匹配规则一样,字符串中的转义符号例如\n
会被解释为对应的控制符,r'\n'
则不会。
需要了解更多的方法可以查看官方文档
4. reference
比较详细Python正则表达式操作指南(re使用)
python正则表达式re模块详细介绍
Python正则表达式
Python正则表达式的七个使用范例
【循序渐进学Python】12.Python 正则表达式简介
Python doc
Python中使用正则表达式