python正则表达式的以下几个表达式比较疑惑,想清楚之后记录如下:
1、pythopn正则常用的搜索模块主要是re.findall()和re.search(),通常情况下有两种使用方式。通过创建正则类:re.complie()来进行匹配,或者直接使用re.findall()和re.search()进行匹配。
2、两种匹配方式其实都差不多,同一个字段需要多次匹配则用re.compile()匹配,对统一字符串多次处理可以使用第二种方法。
3、深坑!:使用search()返回第一个匹配到的目标的match类,使用findall()返回一个列表。此处有一个巨坑,就是在使用()进行分组的时候,findall()最后得到的结果是()分组里面的结果,而不是匹配到的整个值(search不会),所以如果要匹配整个的话,使用(?:...)前面加问号和冒号才可以一起匹配。出现这个问题的原因是()分组会进入缓存,直接写入最后的列表里。
准确的说是,不加?:返回括号内数据,加了返回整个的数据。匹配位置还是一样的
4、介绍一些基本用法:
你们可以参考:http://www.runoob.com/regexp/regexp-tutorial.html,讲得更好。
匹配多行表达式的时候,千万不要忘记了换行符的存在,不然会匹配不到多行。re.S可以匹配多行,但是换行符是一个符号,跨行匹配的时候不要忘记换行符的匹配,可以用 . 来匹配换行符。
import urllib.request as request
import urllib.parse as parse
import re
s = """<div class="animal">
<p class="name">
<a title="tiger"></a>
</p>
<p class="contents">
Two tigers two tigers run fast
</p>
</div>
<div class="animal">
<p class="name">
<a title="rabbit"></a>
</p>
<p class="contents">
Small while rabbit white and white
</p>
</div>"""
p1=re.compile('<div class="animal">.*? title="(\w+)".*?class="contents".*?\s([\w\b].*?)</p>.*?</div>',re.S)
# print(re.findall(r"2000(?=(?:windows|Windows))", x))
r=p1.findall(s)
print(r)
5、个人见解:
在findall里面使用括号分组的时候,一定不要忘了?:。还有正向预匹配格式: aaa(?=...)匹配整个格式但是只获取前面的aaa
匹配一串字符串的所有windows2000或Windows2000的2000:
x="Windows2000windows2000windows2000Windows2000"
print(re.findall(r"2000(?=(?:windows|Windows))", x))
>>>['2000', '2000', '2000']
其他的情况均如上代码所示。
另:附上预匹配的四种情况。用处很大希望自己能记住。。。。
(?:pattern) | 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。 |
(?=pattern) | 正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?!pattern) | 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?<=pattern) | 反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows "能匹配"2000Windows "中的"Windows ",但不能匹配"3.1Windows "中的"Windows "。 |
(?<!pattern) | 反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows "能匹配"3.1Windows "中的"Windows ",但不能匹配"2000Windows "中的"Windows "。 |
re模块
flags 参数的使用:辅助正则表达式,丰富匹配结果,使用为re.I或re.S等
I == IGNORECASE 匹配时忽略字母的大小写
S == DOTALL 作用于元字符 . 使其可以匹配换行
M == MULTILINE 作用于^ $ 使其可以匹配每一行开头结尾位置
X == VERBOSE 可以给正则添加注释
类方法:
regex = compile(pattern,flags = 0),方法和re.的方法一样。
功能 : 生成正则表达式对象
参数 : pattern 正则表达式,flags 功能标志位,丰富正则表达式的匹配功能
返回值 : 返回正则表达式对象
compile对象属性:
flags : 标志位
pattern : 正则表达式
groups: 有多少子组
groupindex : 捕获组形成组名和序列号的字典
组名为键,第几组为值
regex.findall(string,pos,endpos)
功能 :从目标字符串查找正则匹配内容
参数 : string 目标字符串
pos 匹配目标的起始位置
endpos 匹配目标的终止位置
返回值 : 返回匹配到的内容
如果正则有子组则只返回子组对应内容
re.findall(pattern,string,flags)
功能 :从目标字符串查找正则匹配内容
参数 : pattern 正则表达式,string 目标字符串,flags 标志位
返回值 : 返回匹配到的内容,如果正则有子组则只返回子组对应内容。返回的是一个列表
基本方法:
re.split(pattern,string,flags = 0)
功能:根据正则匹配内容切割字符串
参数: pattern string flags
返回值: 返回列表,列表中为切割的内容
re.sub(pattern,replaceStr,string,max,flags) 只替换一次
功能: 替换正则匹配到的目标子串部分
参数: pattern
replaceStr : 要替换的内容
string
max 最多替换几处 默认全部替换
flags
返回值 : 返回替换后的字符串
re.subn(pattern,replaceStr,string,max,flags) 替换所有
功能: 替换正则匹配到的目标子串部分
参数: pattern
replaceStr : 要替换的内容
string
max 最多替换几处 默认全部替换
flags
返回值 : 返回一个元组,为实际替换了几处和替换后的字符串
re.finditer(pattern,string,flags)
功能: 使用正则表达式匹配目标字符串
参数: pattern string flags
返回值: 返回一个迭代对象,迭代到的内容是一个match对象
fullmatch(pattern,string,flags):功能: 完全匹配目标字符串
match(pattern,string,flags):功能: 从开头位置匹配目标字符串
search(pattern,string,flags)
功能: 正则表达式匹配目标字符串,只匹配第一处
参数: pattern,string,flags
返回值:返回匹配到的match对象
如果没匹配成功返回None
match对象属性
属性变量
pos 匹配目标字符串的开始位置
endpos 匹配目标字符串的结束位置
re 正则表达式
string 目标字符串
lastgroup 最后一组的组名
lastindex 最后一组是第几组
属性方法
span() 匹配内容的开始位置
start() 匹配内容的结束位置
end() 匹配内容的起止位置
group()
功能 : 获取match对象对应的内容
参数 : 默认为0 表示获取整个正则匹配的内容
如果为序列号或者子组名则为获取某个子组匹配的对应内容
返回值:返回得到的子串
groupdict() 获取捕获组名作为键,对应内容作为值的字 典
groups() 获取每个子组匹配内容