使用零宽断言来匹配不包含连续字符串的行

     最近在工作中遇到一个问题,有N个字符串,需要用正则表达式去过滤掉不包含某一个特定连续字符串(比如abc)的字符串。

 

     在网上搜罗了一大把,找到了在Perl 5的正则表达式中有零宽断言这个东西,非常强大,先来了解下零宽断言倒是是什么?

 

     简单的说,零宽断言是查找在某些内容之前或者之后的东西,这样解释起来可能比较抽象,我们来具体看下几种零宽断言:

  • (?=exp):这个零宽断言用来断言自身出现的位置之后能够匹配到表达式exp,考虑下面这一个正则表达式q(?=u),这个正则表达式表示匹配后面的字符是u的q
  • (?!exp):这个零宽断言用来断言自身出现的位置之后不能够匹配到表达式exp,看下面这一个正则表达式q(?!u),这个正则表达式表示匹配后面的字符不是u的q
  • (?<=exp):这个零宽断言用来断言自身出现的位置之前能够匹配到表达式exp
  • (?<!exp):这个零宽断言用来断言自身出现的位置之前不能够匹配到表达式exp

     在理解零宽断言的时候需要注意的一点是它是一种断言,也就是说零宽断言只会告诉你匹不匹配,但是不会“消费”掉字符串内的内容,我用下面的这一个例子来解释这个情况:

 

     我们有一个正则表达式k(?=h)otyn,用它去匹配khotyn,乍看一下这个匹配是会成功的,但是由于零宽断言只做断言,而不会"消费"掉匹配到的字符串,所以事实上,这个正则表达式匹配是一个后面是h的k,并且这个k的后面是otyn,这样这个正则表达式无论什么字符串都会匹配失败(正确的应该是k(?=h)hotyn,不过这样加不加零宽断言并没有意义)。

 

     在理解零宽断言以后,我们来看一下如何来匹配出不包含“abc”的字符串,下面是我写出的结果:

((?!abc).)+

     首先我们看这个正则表达式里面的“(?!abc).”部分,这个部分断言一个空字符后面不能够匹配到字符串abc,并且这个空字符串后面是一个任意字符。

 

     我们来看下下面这一段代码:

Pattern pattern = new Perl5Compiler().compile("((?!abc).)+");
Perl5Matcher matcher = new Perl5Matcher();
System.out.println(matcher.matches("abc", pattern));
System.out.println(matcher.matches("abdas dfas", pattern));

     这段代码的执行结果是:

false
true

     第一个匹配失败是因为在字符'a'前面的空字符后面匹配到了字符串"abc",因此断言失败,从而匹配失败。

 

     第二个匹配成功是因为没有任何一个空字符后面有出现"abc",因为匹配成功。

 

     最后加上+号的原因是因为能够做到完全匹配,因为任何一个字符只要其本身不是‘a’,并且后面不是‘bc’,那么就是能够匹配"(?!abc)."的,因此,只要一个字符串里面不包含abc,那么它就能够完全匹配((?abc).)+

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值