Python 正则表达式(?=...)和(?<=...)符号的使用
作者:勤奋的大熊猫
引言
今天遇到了一个比较棘手的问题,于是终于打算要对正则表达式中的 (?=...)
和 (?<=...)
符号动手了。
正文
(?=...)
表示当 …
匹配时,匹配成功,但不消耗字符串中的任何字符。这个叫做 前视断言 (lookahead assertion)
。比如, Isaac (?=Asimov)
将会匹配 Isaac
,仅当其后紧跟 Asimov
。
在之前的介绍中,为什么要使用 ()
符号以及 ...
符号的含义。事实上,上述的 (?=...)
与 (?<=...)
中的 ...
符号可以被替换为任意的符号,这里为了方便说明问题,我们将 ...
符号替换为 \t
符号。
示例1
import re str1 = 'abc\tdefghi\txyz' print(re.search('(?=\t)', str1)) """ result: <re.Match object; span=(3, 3), match=''> """
可以看到,它匹配到了索引值为 3
的 \t
字符,但是由于它是前视断言,即向前搜索,而我们的匹配项中 (?=\t)
之前并没有任何字符,因此什么也没有匹配到。
示例2
我们对示例 1
中的匹配内容稍作更改。
import re str1 = 'abc\tdefghi\txyz' print(re.search('abc(?=\t)', str1)) """ result: <re.Match object; span=(0, 3), match='abc'> """
此时可以看到,匹配到了字符串 abc
。
示例3
(?<=...)
表示如果 ...
的匹配内容出现在当前位置的左侧,则匹配。这叫做 肯定型后视断言 (positive lookbehind assertion)
。 (?<=abc)def
将会在 abcdef
中找到一个匹配,因为后视会回退 3
个字符并检查内部表达式是否匹配。内部表达式(匹配的内容)必须是固定长度的,意思就是 abc
或 a|b
是允许的,但是 a*
和 a{3,4}
不可以。注意,以肯定型后视断言开头的正则表达式,匹配项一般不会位于搜索字符串的开头。
上面的解释比较抽象,那么具体是什么意思呢?我们看一个例子。
import re str1 = 'abc\tdefghi\txyz' print(re.search('(?<=\t)def', str1)) """ result: <re.Match object; span=(4, 7), match='def'> """
程序先找到 def
字符串,然后再回退一个字符查看 def
前面的字符是否是 \t
字符,如果是,那么就匹配 def
字符串。
示例4
如果我们想要匹配两个 \t 字符中间的部分怎么办呢?
import re str1 = 'abc\tdefghi\txyz' print(re.search('\t(.*)\t', str1)) """ result: <re.Match object; span=(3, 11), match='\tdefghi\t'> """
可以看到,此时,结果中包含了两端的 \t
字符,但是我们不想要它包含 \t
字符。为了实现这一目标,我们可以采用刚才我们提到的后视和前视。
import re str1 = 'abc\tdefghi\txyz' print(re.search('(?<=\t).*(?=\t)', str1)) """ result: <re.Match object; span=(4, 10), match='defghi'> """
可以看到我们匹配到了两个 \t
字符中间的字符串,但是上述写法并不严谨,为了严谨,我们可以使用:
import re str1 = 'abc\tdefghi\txyz' print(re.search('(?<=\t)(.*)(?=\t)', str1)) """ result: <re.Match object; span=(4, 10), match='defghi'> """
到此这篇关于Python 正则表达式(?=...)和(?<=...)符号的使用的文章就介绍到这了,更多相关Python ?=... ?<=... 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!