元字符:匹配字符、匹配位置、匹配数量、匹配模式.
常见元字符列表
. 匹配除换行符以外的任意字符
匹配单词的开始或结束
d 匹配数字
w 匹配字母、数字、下划线或汉字
s 匹配任意空白符,包括空格、制表符(Tab)、换行符、中文全角空格等
^ 匹配字符串的开始
$匹配字符串的结束
常用限定符
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次
常用反义字符
W 匹配任意不是字母、数字、下划线的字符
S 匹配任意不是空白符的字符
D 匹配任意非数字的字符
B 匹配不是单词开头或结束的位置
[^a] 匹配除了a以外的任意字符
[^abcde] 匹配除了a、b、c、d、e这几个字母以外的任意字符
[^(123|abc)] 匹配除了1、2、3或者a、b、c这几个字符以外的任意字符
后向引用:
使用小括号指定一个表达式就可以看做是一个分组。默认情况下,每个分组会自动拥有一个组号,规则是:从左至右,以分组的左括号为标志,第一个出现的分组组号为1
表 常用的分组形势
分类 语法 含义
(exp) 匹配exp,并捕获文本到自动命名的组里
捕获 (?P<name>exp) 捕获exp,并捕获wenben到名称为name的组里
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
(?=exp) 匹配exp前面的位置
零宽断言 (?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp)匹配前面不是exp的位置
注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,只用于提供注释让人阅读
零宽度断言:'','^'匹配的是一个位置,而且这个位置需要满足一定的条件,我们把这个条件称为断言或者零宽度断言。
零宽度正预测先行断言:(?=exp),他断言位置的后面能匹配表达式exp.比如[a-z]*(?=exp)匹配以ing结尾的部分,查找I love cooking and singing时会匹配出cook和sing.
先行断言的执行步骤是从要匹配字符的最右端找到第一个“ing” ,再匹配前面的表达式,如无法匹配则查找第二个。
零宽度正回顾后发断言:(?<=exp),他断言此位置的前面能匹配表达式exp。比如(?<=abc).*匹配以abc开头的字符串的后面部分,可以匹配abcdefgabc中defgabc二不是abcdefg,后发断言和先行断言正好相反,他从要匹配的字符串的最左端开始查找断言表达式,之后再匹配后面的字符串,如果无法匹配则继续查找第二个断言表达式,如此反复。
零宽度负预测先行断言:(?!exp) 断言此位置的后面不能匹配表达式exp。比如((?!abc)w)+匹配不包含连续字符串abc的单词
零宽度负预测后发断言:(?<!exp)断言此位置的前面不能匹配表达式exp.比如(?<![a-z])d{7}匹配前面不是小写字母的七位数字。
用于匹配不包含属性的简单HTML标记内的内容 (?<=<(w+)>).*(?=</1).
贪婪与懒惰
当正则表达式中包含能接受重复的限定符时,通常的行为是(整个表达式能匹配的前提下)匹配尽可能多的字符,
这就是贪婪模式。以表达式aw+b为例,如果搜所a12b34b尽可能多的匹配,左后就会匹配整个a12b34b而不是a12b,
但如果想匹配出a12b,该如何处理呢?就要开启懒惰模式将上面aw+b改为aw+?b就可以啦
懒惰限定符的使用方式
*? 重复任意多次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
??重复0次或1次,但尽可能少重复
{n,m}?重复n到m次,但尽可能少重复
{n,}?重复n次以上,但尽可能少重复
表python的匹配规则
语法 含义 表达式 完整匹配字符串
A 仅匹配字符串开头 Aabc abc
仅匹配字符串末尾 abc abc
(?P<name>) 分组,除了原有编号外在指定一个额外的别名 (?P<word>abc){2} abcabc
(?P=name) 引用别名为<name>的分组匹配到的字符串 (?P<id>d)abc(?P=id) 1abc1,5abc5
python中的匹配处理方法,主要是通过re模块里面的几个方法
1.re.match(pattern,string[,float])
此函数是从输入参数string头位置开始匹配,尝试匹配pattern,一直向后匹配,如果遇到无法匹配或者匹配到最后位置,立即返回None,反之获取匹配的结果
案例,通过运行结果可以知道,此种方法是固定位置的匹配,就是字符串必须从最开始的位置匹配。
import re pattern = re.compile(r'(?:d+)') matchresult1 = re.match(pattern, 'abc123cd345') matchresult2 = re.match(pattern, '123abc4567') if not matchresult1: print('matchresult1 no proper regular the result is None') else: print(matchresult1.groups()) if not matchresult2: print('matchresult2 no proper regular the result is None') else: #group()在分组和未分组的情况下都会返回数据 #groups()只会返回分组情况下,每一组里的值。 print(matchresult2.group())
2.re.search(pattern,string[,flags])
此函数与match方法非常相似,区别在于match()函数只在string的开始位置匹配,search()会扫描整个string查找匹配,
match()只有在起始位置匹配成功后才返回,如果不是比开始位置成功的话,直接返回None
案例 只输出123表名,满足条件立即返回,不会进一步继续寻找其他满足条件的匹配
#将正则表达式编译成pattern对象 pattern2=re.compile(r'd+') #匹配文本 result1=re.search(pattern2,'abc123eff3456dd') if result1: print(result1.group()) else: print('匹配失败哦!')
3.re.split(pattern,string[,maxsplit])
此函数按照能匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定,则将全部分割。
案例输出['abc', 'eff', 'dd']
将正则表达式编译成pattern对象 pattern2 = re.compile(r'd+') print(re.split(pattern2, 'abc123eff3456dd'))
4.re.findall(pattern,string[,flags])
搜索整个string,以列表形式返回能匹配的全部子串
案例输出结果 ['123', '3456']
# 将正则表达式编译成pattern对象 pattern2 = re.compile(r'd+') print(re.findall(pattern2, 'abc123eff3456dd'))
5.re.finditer(pattern,string[,flags])
搜索整个string以迭代器的形式返回能匹配的全部Match对象
# 将正则表达式编译成pattern对象 pattern2 = re.compile(r'd+') matchiter = re.finditer(pattern2, 'abc123eff3456dd') for match in matchiter: print(match.group())
6.re.sub(pattern,repl,string[,count])
使用repl替换string中每一个匹配的子串后返回替换后的字符串。当repl是一个字符串时,可以使用id或g<id>、
g<name>引用分组,但不能使用编号0,当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回
一个字符串用于替换(返回的字符串不能引用分组)。count用于指定最多替换的次数,不指定时全部替换
案例如下
import re p5 = re.compile(r'(?P<world1>w+) (?P<world2>w+)') # 使用名称 s = 'i say, hello world!' print(p5.sub(r'g<world2> g<world1>', s)) print('--------------------') print(p5.sub(r'2 1', s)) print('--------------------') def func(m): return m.group(2).title() + ' ' + m.group(1).title() print(p5.sub(func, s))
7.re.subn(pattern,repl,string[,count])
返回(sub(repl,string[,count]),替换次数).
Match对象的属性
string:匹配时使用的文本
re:匹配时使用的Pattern对象
pos:文本中正则表达式开始搜索的索引。
endpos:文本中正则表达式结束搜索的索引。
lastindex:最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None
lastgroup:最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None
Match 对象的方法
group([group1,...]):获得一个或多个分组截获的字符串,指定多个参数时将以元组形式返回。group1可以使用
编号也可以使用别名,编号0代表整个匹配的子串,不填写参数是,返回group(0)。没有截获字符串的组返回None
截获多次的组返回最后一次截获的子串。
groups([default]):以元组形式返回全部分组截获的字符串。相当于调用group(1,2,3...last).default表示没有截获字符串的组以这个值代替
默认为None
groupdict([default]):返回以有别名的组的别名为键,以该组截获的子串为值得字典,没有别名的组不包含在内。default含义同上
start([group]):返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0
end([group]):返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1).group默认值为0
span([group]):返回(start(group),end(group))。
expand(template):将匹配到的分组代入template中然后返回。template中可以使用id或g<id>、g<name>引用分组,
但不能使用编号0. id与g<id>是等价的。
案例
print('match的用法!') pattern = re.compile(r'(w+) (w+) (?P<word>.*)') match = pattern.match('I love you!') print('match.string:', match.string) print('match.re:', match.re) print('match.pos:', match.pos) print('match.endpos:', match.endpos) print('match.lastindex:', match.lastindex) print('match.lastgroup:', match.lastgroup) print('match.group(1,2):', match.group(1, 2)) print('match.groups():', match.groups()) print('macth.groupdict():', match.groupdict()) print('match.start(2):', match.start(2)) print('match.end(2):', match.end(2)) print('match.span(2):', match.span(2)) print(r'match.expand(r"2 1 3"):', match.expand(r'2 1 3'))