关于python正则表达式中的否定预查
好久没写过东西了,水一点最近项目中接触比较多的关于正则的东西吧。
写正则的时候经常会遇到的一个问题是,如果我希望排除某种模式的时候该怎么做。如果是单个字符的话,我们自然可以用[^A-Z]
之类的做法,但如果是比较复杂的模式呢?这就牵涉到否定预查。
之前有见过别人的正则里有?!
这样的东西,以前并没有完全理解这个玩意儿,现在知道了,这就是否定预查。
正向否定预查(只查后面)
即使用?!
,不过要注意,预查不占用字符,单独的?!
无法匹配任何字符,后面需要加其他东西才行。
举个例子:
pat = 'x(?!:)'
这里(?!:)
不占用字符,后面没有东西,所以无法指向任何模式,因而只能匹配x
。
再来一个:
pat = 'x(?!:).'
此处(?!:)
指向后面的.
,代表.
可以是其他任何东西,但不能是:
。
还有个例子:
pat = 'abc(?!(123))\d+'
此处(?!(123))
指向后面的\d+
,代表\d+
可以是任何东西,但不能是123
开头。
所以,总结一下,正向否定预查的结构基本上就是'(模式A)(?!(否定模式B))(模式C)'
,理解的时候可以按照'(模式A)(模式C)'
来理解,但这里的模式C
是有条件的,即它可以是任何符合模式C
的东西,但起始部分不能符合否定模式B
。
例如'abc(?!(123))\d+'
,我们可以当成'abc\d+'
来理解,但这个\d+
是有条件的,即可以是任何符合\d+
的东西,但不能是123
开头。
那有人可能要问,如果我只想排除123
(完全符合,只有123
),但可以是1234
或者12345
呢?给否定预查的条件加上结尾符号$
即可:
pat = 'abc(?!(123)$)\d+'
反向否定预查(只查前面)
反向否定预查与正向否定预查是类似的,只不过?!
变成了?<!
,其结构是'(模式A)(?<!(否定模式B))(模式C)'
,理解的时候同样可以按照'(模式A)(模式C)'
来理解,但这里的是有条件的换成了模式A
,即它可以是任何符合模式A
的东西,但末尾部分不能符合否定模式B
。
简单的例子:
pat = '\d+(?<!(123))abc'
此处(?!(123))
指向前面的\d+
,代表\d+
可以是任何东西,但末尾部分不能是123
。
也就是说我们可以当成'\d+abc'
来理解,但这个\d+
是有条件的,即可以是任何符合\d+
的东西,但不能是123
结尾。
同样地,如果只想完全匹配123
而不错杀4123
这种的话,加个开头符号^
即可:
pat = '\d+(?<!^(123))abc'
大体如此。部分内容参考了https://www.jianshu.com/p/8bf162425d83