正则表达式断言
我们可能经常有这样的需求匹配一个不包括某字符串的字符串
比如说有如下行:
11111
666
3333
我们要排除所有非666的行,可能有同学会这样[^666]或者[^(666)]
这样是不科学的因为[]表达的是一个字符,这样只能排除非6字符。
正确是写法应该是(个人的写法,应该有更好的实现):
^(?!666).*$|666.+
为什么这种写法,是什么意思呢?要读懂它,我们先要弄懂正则表达式中的断言或者说非捕获匹配
下面切一个JDK文档对正则表达式的说明:
特殊构造(非捕获) | |
---|---|
(?:X) | X,作为非捕获组 |
(?idmsux-idmsux) | Nothing,但是将匹配标志i d m s u x on - off |
(?idmsux-idmsux:X) | X,作为带有给定标志 i d m s u x on - off |
(?=X) | X,通过零宽度的正 lookahead |
(?!X) | X,通过零宽度的负 lookahead |
(?<=X) | X,通过零宽度的正 lookbehind |
(?<!X) | X,通过零宽度的负 lookbehind |
(?>X) | X,作为独立的非捕获组 |
下面我们来对这些表达式做通俗的解释
首先他们都是组合表达式,多个字符表示一个含义,不像我们大多数时候^表示大头$表示结尾,\d表示数字等,而这里?:、?<=、?i 等都是多个字符表示一个意思拆开了都没啥意义。而且这些表达式都是放在一个组里面的。所以需要理解组的概念作为前提。
(?:X)
例子:666888
表达式:(?:666)888
匹配结果:true
查询结果:666888
解释:
这个正则表达式总共有2个组,整体一个组,(?:666)一个组,但是(?:666)不捕获所以查询结果只有整体组
(?idmsux-idmsux)
(?idmsux-idmsux:X)
例子:qianQian
表达式:(?i)qianqian 或者 (?i:qianqian)
匹配结果:true
解释:
这个官方文档看起来有点头晕,其中(?!)表示关闭大小写敏感匹配你也可以指定特定的字符串关闭大小写敏感比如第二种写法,反之(?-i)是打开大小写敏感匹配
(?=X)
列子:666888
表达式: 666(?=888)
匹配结果:false
查找结果:666
解释:
首先匹配是false,如果你要true也可以改成666(?=888)888就可以true了,为什么呢,(?=888)的意思是虽然我匹配888但是我不捕获它,也就是JDK文档说的“正”,通过匹配但是不获取值,这样就导致最终的查询值是666和原始值不一致那么就是false,如果你用group查找就可以得到666,而且它是lookahead字面理解就是向前看,也就是说group查找的时候是向前看查找打前面的匹配,这里就是666了
(?!X)
例子:666888
表达式:666(?!77)
匹配结果:false
查询结果:666
解释:
这个就是我们开始匹配非字符串用到的东西,他和(?=)正好相反,就是非的意思,JDK文档说的是”负”,非77字符串但是向前看是666正好可以匹配66688,所有非字符串我们就这样写了^(?!666).*$|666.+前半部分^(?!666).*$非666打头任何字符串可以通过匹配,但是如果一个字符串以666打头又不是666字符串肿么办呢?所以或上了后半部分666.+
(?<=X)
(?<!X)
解释这个和(?=X)、(?!X)一个意思唯一的区别它是向后看,也就是说group查找的是它后面字符串。
上一篇: python 正则获取字符串前的数字