python正则表达式re使⽤模块(match()、search()和
compile())
摘录 python核⼼编程
python的re模块允许多线程共享⼀个已编译的正则表达式对象,也⽀持命名⼦组。下表是常见的正则表达式属性:
函数/⽅法描述
仅仅是re模块函数
compile(pattern,flags=0)使⽤任何可选的标记来编译正则表达式的模式,然后返回⼀个正则表达式对象
re模块函数和正则表达式对象的⽅法
match(pattern,string,flags=0)尝试使⽤带有可选标记的正则表达式的模式来匹配字符串,成功则返回匹配的对象,失败则返回None
search(pattern,string,flags=0)使⽤可选标记搜索字符串中第⼀次出现的正则表达式模式,成功则返回匹
配对象,失败则返回None
findall(pattern,string[,flags])查字符串中所有(⾮重复)出现的正则表达式模式,返回⼀个匹配列表
finditer(pattern,string,[,flags])和findall()函数相同,但返回的是⼀个迭代器。对于每次匹配,迭代器都返回⼀个匹配对象
split(pattern,string,max=0)根据正则表达式的模式分隔符,split函数将字符串分割为列表,然后返回成功匹配的列表,分割最多操作max次(默认分割所有匹配成功的位置)
re模块函数和正则表达式对象⽅法
sub(pattern,repl,string,count=0)使⽤repl替换正则表达式模式在字符串中出现的位置,除⾮定义count,否则替换所有
purge()清除隐式编译的正则表达式模式
常⽤的匹配对象⽅法
group(num=0)返回整个匹配对象,或者编号为num的特定⼦组
groups(default=None)返回⼀个包含所有匹配⼦组的元组(如果没有,则返回⼀个空元组)
groupdict(default=None)返回⼀个包含所有匹配的命名⼦组的字典,所有⼦组名称作为字典的键(如没有,则返回⼀个空字典)
常⽤的模块属性
re.I、re.IGNORECASE不区分⼤写的匹配
re.L、re.LOCALE根据所使⽤的本地语⾔环通过\w\W\b\B\s\S实现匹配
re.M、re.MULTILINE^和$分别匹配⽬标字符串中⾏的起始和结尾,⽽不是严格的匹配整个字符串本⾝的开始和结尾
re.S、re.DOTALL点号.通常匹配除了换⾏符\n之外的所有单个字符,该标记表⽰点号能够匹配全部字符
re.X、re.VERBOSE通过反斜线转义,否则所有空格加上#(以及在该⾏中所有后续问题)都被忽略,除⾮在⼀个字符类中或者允许注释并且提⾼可读性compile()编译正则表达式
在模式匹配发⽣之前,正则表达式模式必须编译成正则表达式对象,⽽且正则表达式在执⾏的过程中可能进⾏多次的⽐较操作。所以,强烈建议使⽤compile函数进⾏预编译,⽤以提升程序的执⾏性能。其实所有的模块函数会对已编译的对象进⾏缓存。
匹配对象及其group()和groups()⽅法
处理正则表达式的时候,除了正则表达式对象外,还有⼀个叫做匹配对象的类型。成功调⽤match()和search()返回的对象就是匹配对象。匹配对象有两个主要的⽅法:group()和groups()函数。⼆者的区别在于:前者可以返回整个匹配对象或者特定⼦组,后者仅返回包含全部⼦组的元组。
match()⽅法实现匹配字符串
match()⽅法视图从字符串的起始位置部分对模式进⾏匹配,成功则返回⼀个匹配对象,失败返回None,⽽匹配对象的group()⽅法能够显⽰成功的匹配:
>>> import re
>>> m = re.match('foo','foo')
>>> m
<_sre.SRE_Match object; span=(0, 3), match='foo'>
>>> if m is not None:
... m.group()
...
'foo'
>>> n = re.match('hello,foo!','foo')
>>> if n is not up()
...
>>> n
第⼆个例⼦中,由于foo并不是在开始的位置,所有没有成功。
search()在⼀个字符串中查模式
search()的⼯作⽅式和match()完全⼀致,只是search()会⽤他的字符串参数,在任意位置对给定正则表达式模式搜索第⼀次出现的匹配情况。成功则返回匹配对象,否则返回None:
>>> n = re.match('foo','hello,foo!')
>>> if n is not None:ngroup()
...
>>>
>>> n = re.search('foo','hello,foo!')
>>> if n is not up()
...
'foo'
匹配多个字符
>>> bt = 'bat|bet|bit'
>>> m = re.match(bt,'bat')
>>> if m is not up()
...
'bat'
>>> m = re.match(bt,'blt')
>>> if m is not up()
...
>>> m = re.match(bt,'he bit me')
>>> if m is not up()
...
>>> m = re.search(bt,'he bit me')
>>> if m is not up()
...
'bit'
匹配任何单个字符
先看⼀个点号不能匹配换⾏符的⽰例:
>>> end = '.end'
>>> m = re.match(end,'bend')
>>> if m is not up()
...
'bend'
>>> m = re.match(end,'\nbend')
>>> if m is not up()
...
>>> m = re.search(end,'The end')
>>> if m is not up()
...
' end
再看⼀下搜索⼀个真正的句点的⽰例:
>>> patt314 = '3.14'
>>> pi_ptt = '3\.14'
>>> m = re.match(pi_ptt,'3.14')
>>> if m is not up()
.
..
'3.14'
>>> m = re.match(patt314,'3014')
>>> if m is not up()
...
'3014'
>>> m = re.search(patt314,'3.14')
>>> if m is not up()
...
'3.14'
>>> m = re.match(pi_ptt,'3014')
>>> if m is not up()
...
上述例⼦⼜让我们强化认识了'3.14'和'3\.14'的区别。
创建字符集
下⾯的⽰例,⽤于展⽰[cr][23][dp][o2]和r2d2|c3po之间的区别:(会发现r2d2|c3po的限制将⽐[cr][23][dp][o2]更为严格)>>> m = re.match('[cr][23][dp][o2]','c3po')
>>> if m is not up()
...
'c3po'
>>> m = re.match('[cr][23][dp][o2]','c2do')
>>> if m is not up()
...
'c2do'
>>> m = re.match('r2d2|c3po','c2do')
>>> if m is not up()
...
>>> m = re.match('r2d2|c3po','r2d2')
>>> if m is not up()
...
'r2d2'
重复、特殊字符以及分组
正则表达式最常见的情况包括:特殊字符的使⽤、正则表达式模式的重复出现、使⽤⼩括号对匹配模式的各部分进⾏分组和提取
我们可以使⽤正则表达式'\w+@\w+\'表⽰⼀个简单的邮件地址。当我们需要再域名前加上主机名,例如,那就必须修改现有的正则表达式。同时,为了表⽰主机名是可选的,需要创建⼀个模式来匹配主机名,使⽤?操作符来表⽰该模式出现0或者⼀次:
\w+@(\w+\.)?\w+\
>>> patt = '\w+@(\w+\.)?\w+\'
>>> re.match(patt,'somebody@xxx').group()
'somebody@xxx'
>>> re.match(patt,'').group()
''
>>> re.match(patt,'z').group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
针对上述例⼦的最后⼀句,下⾯进⾏扩展,允许任意数量的中间⼦域名存在:
>>> patt = '\w+@(\w+\.)*\w+\'
>>> re.match(patt,'z').group()
'z'
⼀般的,采⽤使⽤⼩括号来匹配和保存⼦组,以便于后续处理,⽽不是确定⼀个正则表达式匹配之后在⼀个单独的⼦程序⾥⾯⼿动编码来解析字符串:
>>> m = re.match('\w\w\w-\d\d\d','abc-123')
>>> if m is not up()
...
'abc-123'
>>> m = re.match('\w\w\w-\d\d\d','abc-xyz')
>>> if m is not up()
...
扩展,修改上述正则表达式,使该正则表达式能够提取字母数字字符串和数字:
>>> m = re.match('(\w\w\w)-(\d\d\d)','abc-123')
>>> m.group()
'abc-123'
>>> m.group(1)
'abc'
>>> m.group(2)
'123'
>>> m.groups()
('abc', '123')
下⾯的例⼦展⽰了不同的分组排列,以及group()和groups()函数的执⾏情况:
>>> m = re.match('ab','ab')
>>> m.group()
'ab'
>>> m.groups()
()
>>> m = re.match('(ab)','ab')
>>> m.group()
'ab'
>>> m.group(1)
'ab'
>>> m.group(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: no such group
>>> m.groups()
('ab',)
>>> m = re.match('(a)(b)','ab')
>>> m.group()
'ab'
>>> m.group(1)
'a'
>>> m.group(2)
'b'
>>> m.groups()
('a', 'b')
>>> m = re.match('(a(b))','ab')
>>> m.group()
'ab'
>>> m.group(1)
'ab'
>>> m.group(2)
'b'
>>> m.groups()
('ab', 'b')
匹配字符串的起始和结尾以及单词边界
下⾯例⼦展⽰了表⽰位置的正则表达式操作符。更多的⽤于表⽰搜索⽽不是匹配,因为match()总是从字符串开始位置进⾏匹配:
>>> import re
>>> m = re.search('^The','The end')
>>> if m is not None:
... m.group()
...
'The'
>>> m = re.search('^The','end The')
>>> if m is not None:
... m.group()
...
>>> m = re.search(r'\bthe','bite the dog')
>>> if m is not None:
... m.group()
...
'the'
>>> m = re.search(r'the','bite the dog')
>>> if m is not None:
.
.. m.group()
...
'the'
>>> m = re.search(r'the','bitethe dog')
>>> if m is not None:
... m.group()
...
'the'regex匹配
>>> m = re.search(r'\Bthe','bite the dog')
>>> if m is not None:
... m.group()
.
..
使⽤findall()和finditer()查每⼀次出现的位置
findall()查询字符串中某个正则表达式模式全部的⾮重复出现情况。于search()执⾏的搜索字符串类似,但是不同之处在于:findall()总是返回⼀个列表,列表按顺序包含所有成功匹配的部分:
>>> re.findall('car','carry the barcardi to the car')
['car', 'car', 'car']
finditer()于findall类似,但是返回的是⼀个迭代器,使得更节省内存。(对于迭代器,可以使⽤迭代器相关的知识提取内容)
使⽤sub()和subn()搜索和替换
两者的作⽤基本⼀致,都是将某个字符串中所有匹配正则表达式的部分进⾏某种形式的替换,相⽐于sub(),subn()还返回⼀个表⽰替换的总数,替换后的字符串和表⽰替换总数的数字⼀起作为⼀个拥有两个元素的元组返回:
>>> re.subn('X','Mr.Smith','attn:X\n\nDear X,\n')
('attn:Mr.Smith\n\nDear Mr.Smith,\n', 2)
>>> print(re.sub('X','Mr.Smith','attn:X\n\nDear X,\n'))
attn:Mr.Smith
Dear Mr.Smith,
在限定模式上使⽤split()分割字符串
先来⼀个普通的字符串分割:
>>> re.split(':','str1:str2:str3')
['str1', 'str2', 'str3']
再来见识⼀下巨⼤威⼒的分割效果:例如⽤于web站点的简单解析器,这是普通的字符串分割没有的强⼤的处理⽅式
>>> DATA = (
... 'Moutain view, CA 94040',
... 'Sunny, CA',
... 'Los Altos, 94023',
... 'Cuper 95014',
... 'Palo Alto CA',
... )
>>> for i in DATA:
... print(re.split(', |(?= (?:\d{5}|[A-Z]{2})) ',i))
...
['Moutain view', 'CA', '94040']
['Sunny', 'CA']
['Los Altos', '94023']
['Cuper', '95014']
['Palo Alto', 'CA']
上述例⼦中的正则表达式使⽤了⼀个组件:使⽤split语句基于逗号分割字符串,或者如果空格紧跟在五个数字或者两个⼤写字母之后,就⽤
split语句分割该空格。⽽这种分割效果很难⽤str.split()达到。
这⾥涉及到的正则表达式的扩展符号的使⽤,⾜够让我们另写⼀篇⽂章介绍了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论