python正则表达式
前向匹配和后向匹配
术语介绍
模式正向向后查找 positive look-behind(?<=)
正向向前查找positive look-ahead(?=)
负向向后查找negative look-behind(?<!)
负向向前查找negative look-ahead(?!)
正向和负向指的分别是 出现则匹配 和 不出现则匹配
1. (?<=[pattern])和 (?<![pattern])
- 功能
匹配[pattern]的内容,但在结果中并不会返回这个子模式 - 用法
(?<=[pattern])
是放在待匹配正则表达式 之前的,(?=[pattern])
是放在待匹配正则表达式之后; 相关用法如下所示
正则表达式 | 是否正确 |
---|---|
(?<=[pattern1])[pattern2](?=[pattern3]) | ✅ |
(?=[pattern1])[pattern2](?<=[pattern3]) | ❌ |
[pattern4](?<=[pattern1])[pattern2](?=[pattern3]) | ✅ |
[pattern4](?<=[pattern1])[pattern2](?=[pattern3])[pattern5] | ✅ |
(?<=[pattern1])[pattern2] | ✅ |
[pattern2](?=[pattern1]) | ✅ |
要匹配的正则表达式在(?<=[pattern])
后面,所以匹配的时候是往后看的,所以(?<=[pattern])
就叫look-behind。需要注意(?<=[pattern])
里的子模式pattern的宽度一定要确定,也就是子模式中不能出现*?+
等模式
- 实验
识别出下面句子里所有的姓氏
Dr.David Jone, Ophthalmology, Ms.Cindy Harriman, Registry, Mr.Chester Addams, Mortuary, Dr.Hawkeye Pierce, Surgery
每个姓氏前面都是空格,后面都是逗号,因此可以写成如下形式
import re
pattern=re.compile(r'(?<=\s)([A-Za-z]*)(?=,)')
string = "Dr.David Jone, Ophthalmology, Ms.Cindy Harriman, Registry, Mr.Chester Addams, Mortuary, Dr.Hawkeye Pierce, Surgery"
res = pattern.findall(string)
print(res)
输出结果
['Jone', 'Ophthalmology', 'Harriman', 'Registry', 'Addams', 'Mortuary', 'Pierce']
2. (?<![pattern])和(?![pattern])
- 功能
如果没出现[pattern]的内容就匹配,但在结果中并不会返回这个子模式 - 用法
(?<![pattern])
是放在待匹配正则表达式之前的,(?![pattern])
是放在待匹配正则表达式之后
3. 非捕获组(?:[pattern])
-
功能
匹配[pattern],但不会记录这个组 -
实验
import re
s = 'Cake is better than potato'
pattern = re.compile(r'(?:is\s)better(\sthan)')
print("out1:", pattern.search(s).group(0))
print("out2:", pattern.search(s).group(1))
输出
out1: is better than
out2: than
Match对象的group(num/name)
方法返回的是对应组的内容,子模式序号从1开始。group(0)
返回的是整个模式的匹配内容(is better than)
,而group(1)
返回的是第1个子模式的内容( than)
。
这里可以发现第1个子模式对应的是(\sthan)
而不是(?:is\s)
,也就是说(?:is\s)
这个组未被捕获(没有被记录)
前向查找和非捕获组的区别
positive look-ahead(正向向前查找)
(?=[pattern])
和 positive look-behind(正向向后查找)
(?<=[pattern])
是 出现[pattern]则匹配,但并不返回该子模式匹配的内容,它们和(?:[pattern])
有什么区别呢?
import re
s = 'Cake is better than potato'
pattern1 = re.compile(r'(?:is\s)better(\sthan)')
pattern2 = re.compile(r'(?<=is\s)better(\sthan)')
print("p1g0:", pattern1.search(s).group(0))
print("p1g1:", pattern1.search(s).group(1))
print("p2g0:", pattern2.search(s).group(0))
print("p2g1:", pattern2.search(s).group(1))
输出
p1g0: is better than
p1g1: than
p2g0: better than
p2g1: than
结论
(?<=[pattern])
和(?=[pattern])
是匹配到了[pattern]
不会返回、亦不会记录(捕获)[pattern]子模式,所以在上面例子中整个模式的匹配结果中没有 is空格。(?:[pattern])
是匹配到了[pattern]
会返回,但不会记录(捕获)[pattern]子模式,所以在上面例子中整个的匹配结果中有 is空格。(?:[pattern])
,(?<=[pattern])
,(?=[pattern])
的共同点是 都不会记录[pattern]子模式(子组),所以上面例子中group(1)找到的第1个组的内容是(\sthan)
匹配到的空格than
参考
Python正则表达式细节小记