您的位置:首页 > 其它

正则表达式里字符串”不包含”匹配技巧

2017-03-23 15:29 519 查看
经常我们会遇到想找出不包含某个字符串的文本,程序员最容易想到的是在正则表达式里使用,^(hede)来过滤”hede”字串,但这种写法是错误的。我们可以这样写:[^hede],但这样的正则表达式完全是另外一个意思,它的意思是字符串里不能包含‘h’,‘e’,‘d’三个但字符。那什么样的正则表达式能过滤出不包含完整“hello”字串的信息呢?

事实上,说正则表达式里不支持逆向匹配并不是百分之百的正确。就像这个问题,我们就可以使用否定式查找来模拟出逆向匹配,从而解决我们的问题:

^((?!hede).)*$


上面这个表达式就能过滤出不包含‘hede’字串的信息。我上面也说了,这种写法并不是正则表达式“擅长”的用法,但它是可以这样用的。

解释

一个字符串是由n个字符组成的。在每个字符之前和之后,都有一个空字符。这样,一个由n个字符组成的字符串就有n+1个空字符串。我们来看一下“ABhedeCD”这个字符串:

+--+---+--+---+--+---+--+---+--+---+--+---+--+---+--+---+--+
S = |e1| A |e2| B |e3| h |e4| e |e5| d |e6| e |e7| C |e8| D |e9|
+--+---+--+---+--+---+--+---+--+---+--+---+--+---+--+---+--+

index    0      1      2      3      4      5      6      7


所有的e编号的位置都是空字符。表达式(?!hede).会往前查找,看看前面是不是没有“hede”字串,如果没有(是其它字符),那么.(点号)就会匹配这些其它字符。这种正则表达式的“查找”也叫做“zero-width-assertions”(零宽度断言),因为它不会捕获任何的字符,只是判断。

在上面的例子里,每个空字符都会检查其前面的字符串是否不是‘hede’,如果不是,这.(点号)就是匹配捕捉这个字符。表达式(?!hede).只执行一次,所以,我们将这个表达式用括号包裹成组(group),然后用(星号)修饰——匹配0次或多次:((?!hede).)。

你可以理解,正则表达式((?!hede).)*匹配字符串”ABhedeCD”的结果false,因为在e3位置,(?!hede)匹配不合格,它之前有”hede”字符串,也就是包含了指定的字符串。

在正则表达式里, ?! 是否定式向前查找,它帮我们解决了字符串“不包含”匹配的问题。

例子

1.例子,查找不以baidu开头的字符串。

baidu.com

sina.com.cn

正则:^(?!baidu).*匹配结果就是第2行,也就是第1行被排除了这里使用了零宽度断言(?!exp),注意,我们有一个向前查找的语法(也叫顺序环视)(?=exp)(?=exp)会查找exp之前的【位置】如果将等号换成感叹号,就变成了否定语义,也就是说查找的位置的后面不能是exp一般情况下?!要与特定的锚点相结合,例如行开头或者行结尾,那么上面的例子的意思如下:

^(?!baidu).*$ 先匹配一个行开头的位置,并且要求接下来的位置的后面不是baidu这个字符串。这样由于第一行^之后的位置后面是baidu所以匹配失败,被排除在外了。

2.例子,查找不以com结尾的字符串。

www.sina.com.cn

www.educ.org

www.hao.cc

www.baidu.com

www.123.com

正则 ^.*?(?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐