标准库:一些最爱
re
re模块包括对正則表達式的支持,由于以前系统学习过正則表達式,所以基础内容略过,直接看python对于正則表達式的支持。
正則表達式的学习,见《Mastering Regular Expressions》(精通正則表達式)
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.searching(string)(pat是用compile创建的模式对象)。经过compile转换的正則表達式对象也能用于普通的re函数。
函数re.search会在给定字符串中寻找第一个匹配给定正則表達式的子字符串。一旦找到子字符串,函数就会返回MatchObject(值为True),否则返回None(值为False)。
函数re.match会在给定字符串的开头匹配正則表達式。因此,match(‘p’,’python’)返回真,而re.match(‘p’,’www.python.org’)则返回假(None)。
注意:假设模式与字符串的開始部分相匹配,那么match函数会给出匹配的结果,而模式并不须要匹配整个字符串。假设要求模式匹配整个字符串,那么能够在模式的结尾加上美元符号。美元符号会对字符串的末尾进行匹配,从而顺延了整个匹配。
函数re.split会依据模式的匹配项来切割字符串。类似于字符串的split,只是是用完整的正則表達式取代了固定的分隔符字符串。
>>> import re
>>> some_text="alpha, beta .... gamma delta"
>>> re.split('[. ]+',some_text)
['alpha,', 'beta', 'gamma', 'delta']
>>> re.split('ta',some_text)
['alpha, be', ' .... gamma del', '']
maxsplit參数表示字符串最多能够切割成的部分数:
>>> re.split('[. ]+',some_text,maxsplit=1)
['alpha,', 'beta .... gamma delta']
>>> re.split('[. ]+',some_text,maxsplit=2)
['alpha,', 'beta', 'gamma delta']
>>> re.split('[. ]+',some_text,maxsplit=0)
['alpha,', 'beta', 'gamma', 'delta']
>>> re.split('[. ]+',some_text,maxsplit=-2)
['alpha, beta .... gamma delta']
函数re.findall以列表形式返回给定模式的全部匹配项:
>>> re.findall('[. ]+',some_text)
[' ', ' .... ', ' ']
函数re.sub的作用在于:使用给定的替换内容将匹配模式的子字符串(最左端而且非重叠的子字符串)替换掉。
>>> re.sub('{name}',some_text,'Dear {name}')
'Dear alpha, beta .... gamma delta'
re.escape是一个非常有用的函数,它能够对字符串中全部可能被解释为正则运算符的字符进行转义的应用函数。
>>> re.escape('`~-_=+[{]}|;:"/?.>,<')
'\`\~\-\_\=\+\[\{\]\}\\\|\;\:\"\/\?\.\>\,\<'
>>> re.escape('www.baidu.com')
'www\.baidu\.com'
匹配对象和组
对于re模块中那些可以对字符串进行模式匹配的函数而言,当能找到匹配项的时候,它们都会返回MatchObject对象。这些对象包括匹配模式的子字符串的信息。它们还包括了哪个模式匹配了子字符串哪部分的信息——组(group)。
组就是放置在圆括号内的子模式。组的序号取决于它左边的括号数。组0就是整个模式。
re匹配对象的一些重要方法
方法 |
描写叙述 |
group([group1,...]) |
获取给定子模式(组)的匹配项 |
start([group]) |
返回给定组的匹配项的開始位置 |
end([group]) |
返回给定组的匹配项的结束位置(和分片一样,不包含组的结束位置) |
span([group]) |
返回一个组的開始和结束位置 |
>>> m=re.match('.{4}://(.{4}).(.{4})..{3}/.{8}','http://blog.csdn.net/signjing')
>>> m.group(1)
'blog'
>>> m.group(2)
'csdn'
>>> m.start(1)
7
>>> m.start(2)
12
>>> m.span(1)
(7, 11)
>>> m.span(2)
(12, 16)
作为替换的组号和函数
见证re.sub强大功能的最简单方式就是在替换字符串中使用组号。在替换内容中以’\n’形式出现的不论什么转义序列都会被模式中与组n匹配的字符串替换掉。
将”http://blog.csdn.net/signjing”中的’/’(不包含http头中的’/’)变为’\’:
>>> pat=r'([^:/])/([^:/]*)'
>>> re.sub(pat,r'1\2','http://blog.csdn.net/signjing')
'http://blog.csdn.net\signjing'
注意:正則表達式非常easy变得难以理解,使用有意义的变量名或加上一两句凝视是非常重要的。
让正則表達式变得更加易读的方式是在re函数中使用VERBOSE标志。它同意在模式中加入空白(空白字符、tab、换行符,等等),re则会忽略它们——除非将其放在字符类或者用反斜线转义。也能够在冗长的正则式中加入凝视。
>>> pat=re.compile(r'''
( #開始第一个组
[^:/] #匹配一个不包含:和/的字符,主要目的是排除http头中的/
) #结束第一个组
/ #匹配/
( #開始第二个组
[^:/]* #匹配随意多个不包含:和/的字符串
) #结束第二个组
''',re.VERBOSE)
>>> re.sub(pat,r'1\2','http://blog.csdn.net/signjing')
'http://blog.csdn.net\signjing'
模板系统
模板是一种通过放入详细值从而得到某种已完毕文本的文件。python有一种高级的模板机制——字符串格式化。但正則表達式能够让系统更加高级。
精通不论什么程序设计语言的最佳方法是实践——測试它的限制,探索它的能力。
练习 匹配字符串
脚本内容
$ cat re-example-1.py
#File : re-example-1.py
import re
text="The Attila the Hun Show"
print text
m=re.match(".",text)
if m: print repr("."),"=>",repr(m.group(0))
m=re.match(".*",text)
if m: print repr(".*"),"=>",repr(m.group(0))
m=re.match("w+",text)
if m: print repr("w+"),"=>",repr(m.group(0))
m=re.match("d+",text)
if m: print repr("d+"),"=>",repr(m.group(0))
运行结果
$ python re-example-1.py
The Attila the Hun Show
'.' => 'T'
'.*' => 'The Attila the Hun Show'
'\w+' => 'The'
练习 提取匹配的子字符串
脚本内容
$ cat re-example-2.py
#File: re-example-2.py
import re
text="2014/06/24"
m=re.match('(d{4})/(d{2})/(d{2})',text)
if m:
print m.group(1,2,3)
运行结果
$ python re-example-2.py
('2014', '06', '24')
练习 查找子字符串
脚本内容
$ cat re-example-3.py
#File: re-example-3.py
import re
text="There is one Date: 2014/6/24 in here!"
m=re.search('(d{4})/(d{1,2})/(d{1,2})',text)
print m.group(1),m.group(2),m.group(3)
month,day,year=m.group(2,3,1)
print month,day,year
date=m.group(0)
print date
运行结果
$ python re-example-3.py
2014 6 24
6 24 2014
2014/6/24
练习 替换子字符串
脚本内容
$ cat re-example-4.py
# File : re-example-4.py
import re
text="You're no fun anymore ..."
print re.sub('fun','interesting',text)
print re.sub("[^w]+","-",text)
print re.sub("S+","-BEEP-",text)
运行结果
$ python re-example-4.py
You're no interesting anymore ...
You-re-no-fun-anymore-
-BEEP- -BEEP- -BEEP- -BEEP- -BEEP-
练习 通过回调函数替换子字符串
脚本内容
$ cat re-example-5.py
#File : re-example-5.py
import re
import string
text="a line of text\012another line of text\012etc..."
def octal(match):
return chr(string.atoi(match.group(1),8))
octal_pattern=re.compile(r"\(ddd)")
print text
print octal_pattern.sub(octal,text)
运行结果
$ python re-example-5.py
a line of text 12another line of text 12etc...
a line of text
another line of text
etc...
练习 匹配多个模式中的一个
脚本内容
$ cat re-example-6.py
#File : re-example-6.py
import re,string
def combined_pattern(patterns):
p=re.compile(
string.join(map(lambda x: "("+x+")",patterns),"|")
)
def fixup(v,m=p.match,r=range(0,len(patterns))):
try:
regs=m(v).regs
except AttributeError:
return None
else:
for i in r:
if regs[i+1] != (-1,-1):
return i
return fixup
patterns=[
r"d+",
r"abcd{2,4}",
r"pw+"
]
p = combined_pattern(patterns)
print p("129391")
print p("abc800")
print p("abc1600")
print p("python")
print p("perl")
print p("tcl")
运行结果
$ python re-example-6.py
0
1
1
2
2
None