python3之正则表达式

一、正则表达式基础

正则表达式是用于处理字符串的强大工具,拥有本身独特的语法以及一个独立的处理引擎,效率上可能否则str自带方法,但功能十分强大。python

正则表达式的大体匹配流程:依次拿出表达式和文本中的字符比较,若是每个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。正则表达式

python支持的正则表达式元字符和语法:工具

模式 描述
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则能够匹配包括换行符的任意字符。
[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c以外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片断,非贪婪方式
re{ n}  
re{ n,} 精确匹配n个前面表达式。
re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片断,贪婪方式
a| b 匹配a或b
(re) G匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 相似 (...), 可是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#...) 注释.
(?= re) 前向确定界定符。若是所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,不然失败。但一旦所含表达式已经尝试,匹配引擎根本没有提升;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否认界定符。与确定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
(?> re) 匹配的独立模式,省去回溯。
\w 匹配字母数字及下划线
\W 匹配非字母数字及下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f].
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9].
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,若是是存在换行,只匹配到换行前的结束字符串。c
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 能够匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等. 匹配一个换行符。匹配一个制表符。等
\1...\9 匹配第n个分组的内容。
\10 匹配第n个分组的内容,若是它经匹配。不然指的是八进制字符码的表达式。

正则表达式修饰符-可选标志spa

正则表达式能够包含一些可选标志修饰符来控制匹配的模式,修饰符被指定为一个可选的标志,多个标志能够经过按位or(|)来指定。3d

修饰符 描述
re.I 使匹配对大小写不敏感
re.L 作本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的全部字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志经过给予你更灵活的格式以便你将正则表达式写得更易于理解。

二、re方法

python从1.5开始增长了re模块,它提供了perl风格的正则表达式模式。code

re模块使python语言拥有所有的正则表达式功能。对象

re模块方法:blog

re.match索引

尝试从字符串的起始位置匹配一个模式,若是不是起始位置匹配成功则返回none。ci

re.match语法:re.match(pattern,string,flags=0)

pattern:匹配的正则表达式,string:要匹配的字符串,flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等。

>>> import re
>>> print(re.match('abc','abcefg').group())  #匹配开头,group方法返回分组字符串。
abc
>>> r1 = re.match('abc','1abcefg')
>>> print(r1)   #开头未匹配到返回none
None

re.search(pattern, string, flags=0)

用于查找字符串中能够匹配成功的子串,从string的开始位置匹配到结尾,匹配成功则返回一个匹配结果再也不向后匹配了,如匹配失败则返回None。

>>> pattern = re.search('w','aw,bw,cw,dw')  #匹配结果
>>> print(pattern)  #返回一个match对象
<_sre.SRE_Match object at 0x7fcfa3566920>
>>> pattern.group()   #获取一个分组截获的字符串
'w'
>>> pattern.start()  #截获字符串的开始索引
1
>>> pattern.end()  #截获字符串的结束索引
2

re.split(pattern, string, maxsplit=0, flags=0)

按照可以匹配的字符串以列表的形式分隔返回不能匹配到的字串,maxsplit用于指定最大分割次数,不指定将所有分割。

>>> print(re.split('[0-9]','a1b2c3'))
['a', 'b', 'c', '']
#返回不能匹配的对象,以列表的形式

re.findall(pattern, string, flags=0)

搜索string,以列表的形式返回所有能匹配到的字串。

>>> print(re.findall('[0-9]','a1b2c3'))
['1', '2', '3']
>>> print(re.findall('\d+','a21b32c35'))
['21', '32', '35']
#以列表的形式返回全部匹配的子串,\d+为匹配1到多个数字

re.finditer(pattern, string, flags=0)

搜索string,返回访问每个匹配结果的match对象的迭代器

>>> pat = re.finditer('\d+','aa123bb456cc')  #返回match对象的一个迭代器
>>> print(pat)
<callable_iterator object at 0x7fcfa354df10>
>>> for i in pat:     #循环迭代器取值
...   print(i.group())
... 
123
456

re.sub(pattern, repl, string, count=0, flags=0)

使用repl替换string中每个匹配的子串后返回替换后的字符串。count用于指定最多替换的次数,不知道时所有替换。

>>> pat = re.sub('\d+','@@@','aaa1bbb22ccc333')
>>> print(pat)   #替换匹配对象
aaa@@@bbb@@@ccc@@@
>>> print(re.sub('\d+','@@@','aaa1bbb22ccc333',count=2))
aaa@@@bbb@@@ccc333  #只替2次匹配到的子串

re.subn(pattern, repl, string, count=0, flags=0)

返回一个元组包含(新的替换字串,数量)

>>> print(re.subn('\d+','@@@','aaa1bbb22ccc333',count=2))
('aaa@@@bbb@@@ccc333', 2)
#返回repl替换的对象和替换的次数

re.compile(pattern,flags=0)

编译一个正则表达式模式,返回一个模式对象

>>> import re
>>> re1 = re.compile(r'hello')   #编译一个正则匹配模式
>>> print(type(re1))
<class '_sre.SRE_Pattern'>  #该模式是一个pattern对象
>>> print(re.match(re1,'hello world').group())
hello

三、match对象方法

patt = re.search('(\d+),(\d+)','11,3dsfdsa3324fdag4556'
>>> print(type(patt))  #返回一个match对象
<class '_sre.SRE_Match'>
#string匹配时使用的文本
>>> print(patt.string)   
11,3dsfdsa3324fdag4556
#re匹配时使用的正则模式(pattern对象)
>>> print(patt.re)
<_sre.SRE_Pattern object at 0x7fcfa3c4b530>
#regs返回分组索引
>>> print(patt.regs)
((0, 4), (0, 2), (3, 4))
#pos开始搜索的索引
>>> print(patt.pos)
0
#endpos结束搜索的索引
>>> print(patt.endpos)
22
#lastindex最后一个被捕获的分组在文本中的索引
>>> print(patt.lastindex)
2
#lastindex最后一个捕获的分组的别名,如没有则返回None
>>> print(patt.lastgroup)
None
#group()得到一个或多个分组截获的字符串
>>> print(patt.group())
11,3
#得到第1个分组的字符串
>>> print(patt.group(1))
11
>>> print(patt.group(2))
3
#groups()以元祖的形式返回所有分组截获的字符串
>>> print(patt.groups())
('11', '3')
#groupdict()返回已有别名的组的别名为健,以该组截获的子串味值的字典
>>> print(patt.groupdict())
{}
#start()返回组截获的子串在string中的起始索引
>>> print(patt.start())
0
>>> print(patt.start(1))
0
#返回第2个分组的起始索引
>>> print(patt.start(2))
3
#stop()返回组截获的子串在string中的结束索引
>>> print(patt.end(2))
4
>>> print(patt.end(1))
2
#返回开始和结束的索引
>>> print(patt.span())
(0, 4)
#返回第1个分组的开始结束索引
>>> print(patt.span(1))
(0, 2)
>>> print(patt.span(2))
(3, 4)