继上一篇博客python正则表达式(一)后,此篇文章主要是重点记录"(?=)"(前向肯定界定符)、"(?!)"(前向否定界定符)、"(?<=)"(后项肯定界定符)以及"(?<!)"(后项否定界定符)的用法。
想要纯文字阐述清楚用法很难,直接看例子。
例一
若想分割一个字符串,分隔符为:",",但是要求当","前后均为数字时才有效。
import re
s = "abc,123,cde,45,fg,123,456,cba,xyz,5jk"
res = re.split(r'(?<=\d),(?=\d)', s)
print(res)
['abc,123,cde,45,fg,123', '456,cba,xyz,5jk']
解析:"(?<=\d),“表示逗号之前要为数字,”,(?=\d)"表示逗号之后要为数字。
例二
若想分割一个字符串,分隔符为:",",但是要求当","前面为数字,后面为字母时才有效。
import re
s = "abc,123,cde,45,fg,123,456,cba,xyz,5jk"
res = re.split(r'(?<=\d),(?=[a-zA-Z])', s)
print(res)
['abc,123', 'cde,45', 'fg,123,456', 'cba,xyz,5jk']
解析:,(?=[a-zA-Z])表示逗号之后为字母。
例三
若想分割一个字符串,分隔符为:",",但是要求当","前面为字母,后面为数字时才生效。
import re
s = "abc,123,cde,45,fg,123,456,cba,xyz,5jk"
res = re.split(r'(?<=[a-zA-Z]),(?=\d)', s)
print(res)
['abc', '123,cde', '45,fg', '123,456,cba,xyz', '5jk']
解析:将例二顺序调过来即可。
例四
若想分割一个字符串,分隔符为:",",但是要求当","前面不能为$并且后面不能为&时才生效。
import re
s = "abc,123$,cde,45,&fg,123,456,cba$,&xyz,5jk"
res = re.split(r'(?<!\$),(?!&)', s)
print(res)
['abc', '123$,cde', '45,&fg', '123', '456', 'cba$,&xyz', '5jk']
解析:"(?<!$),“表示逗号前面不能有 ( 因 为 (因为 (因为是特殊字符,所以加了转义),”,(?!&)“表示逗号后面不能有&,但是写在一起得到的结果却并不是我们想要的,要求逗号前为”KaTeX parse error: Expected 'EOF', got '&' at position 6: "且后为"&̲"时不分割,所以我们想要得到的…’, ‘cde’, ‘45’, ‘&fg’, ‘123’, ‘456’, ‘cba$,&xyz’, ‘5jk’]`
上面那种写法可能是很容易犯的错,这里来一步步解析下,我们可以把逗号的种类分为四种,
- 逗号前面不是"$",并且后面不是"&";
- 逗号前面是"$",但后面不是"&";
- 逗号前面不是"$",但后面是"&";
- 逗号前面是"$",并且后面是"&";
只有第4种情况的逗号不能作为分隔符,其他三种都可以作为分隔符,而我们的表达式实际只表示了第1种情况,当2、3两种情况出现时,表达式不生效,所以我们要写的表达式是前三种情况,也就是第4种情况的取反。
正确的正则分割写法为:re.split(r'(?<!\$),|,(?!&)', s)
,这里面有点绕,需要仔细思考。
注意:这里容易混淆前向界定符和后向界定符的含义,要对逗号之前做一些条件限定,应使用后向界定符;要对逗号之后做一些条件限定,应使用前向界定符。此外,当同时使用前向否定和后向否定做一些条件限定时,注意逻辑上的转变。