Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1023364
  • 博文数量: 157
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1388
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-09 15:37
文章分类

全部博文(157)

文章存档

2023年(9)

2022年(2)

2021年(18)

2020年(7)

2017年(13)

2016年(53)

2015年(55)

我的朋友

分类: 服务器与存储

2015-09-30 10:09:41

转载于:http://www.cnblogs.com/wangqiguo/archive/2012/05/08/2486548.html

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

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

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






正则 ^.*?(? 如果查找以com结尾的字符串则使用正则 ^.*?(?<=com)$或者 ^.*?com$
对正则表达式的解释:^.*?(? 首先匹配行开头,然后是 .*? 这个是忽略优先,也就是优先忽略不匹配任何字符,(?
3.例子查找不含有if的行
if (a>b)
printf("hello");
else if(a printf("hello2");
else
printf("hello3");

正则 ^([^f]|[^i]f)+$
其实这个匹配也是一个排除型字符串的匹配,但是不同于上面两种,因为这里的if可能既不在行开头,也不在行结尾,而是在字符串中间这样就给匹配带来了麻烦,在正则表达式中没有提供类似排除的功能。我们最容易想到的就是下面的正则:
^[^if]+$ 这种写法看起来是那么回事,但是排除型字符组排除的是i和f两个字符,而不是if这个字符串,所以这个正则表达式匹配的是那些既没有i字符也不包含f字符的字符串。但是如果字符串中有一个i或多个i或者有一个或多个f,或者i和f字符都有只不过没有连在一起。这些情况都是我们需要匹配的情况,而我们不能匹配的情况是那些包含if字符串的行,而不是包含i或f字符的行,所以这种写法漏洞很大。

^.*(?!if).*$ 这种写法使用了零宽度断言,表面意思看起来好像是说 任意字符+非if+任意字符 组成了整个字符串,但是仔细研究匹配过程就知道这个是错的,(?if)匹配的是一个位置,所以对于字符串aifb他也是可以匹配到的,而实际上这样的字符正是我们不要的。按照这个正则表达式,对于aifb 首先匹配行首,其次.*是贪婪模式(匹配优先),会一直匹配到字符串的末尾(此时传动装置定位在$位置前面),此时(?!if)需要匹配一个位置,这个位置的后面不能是if,这个时候正好位置在b字符的后面,符合匹配条件,紧接着匹配行尾,到这里整个全局匹配成功。

也就是说对于一个字符串例如我要排除abc这个字串,那么对于任意一个字符串 helloworld abc helloworld 在匹配的时候(?!abc)可以匹配h、e、l、l、o、w、o、r、l、d等这些字符后面的位置,都是成功的。所以匹配根本还没有进行到abc这个地方,(?!abc)就会匹配成功。这个时候根本起不到排除的作用,为什么上面的第1和第2个例子可以呢,因为他们的位置有行首和行尾限定。例如我要匹配行首不是abc的话,那么此时^(?!abc) 这个时候(?!abc)实际上在匹配的时候其传动装置的位置被行首进行了限定,所以对于那些以abc开头的字符串来说就会匹配失败了。

对于正则表达式^.*(?!abc).*$怎么能让第一个.*匹配到 helloworldabcxxx中的helloworld的问题。

对于上面的题目,我们的答案是^([^f]|[^i]f)+$ 其实就将所有的匹配分成了2种情况,一种情况是假设字符串中没有f字符, 自然就不可能有if字符串了,这种情况下匹配的字符串中是不可能有if的。第二种情况就是有f字符,但是我们要求此时f的前面不能是i,所以在有f和没有f两种情况都考虑到的情况下,这个正则就应该可以满足所有的情况了。

其实这个问题的解答是不完美的,对于排除的字符串if只有2个字符i和f字符,我们可以使用这种方式,但是如果我们要排除的是字符串helloworld,这种方法显然就不实用了,那要考虑到多少种情况呢?

在这种情况下我们使用 ^(?!.*helloworld).*$ 正则表达式 我们将第一个.*移到了零宽度断言的里面。在匹配的时候首先匹配行首的位置,然后接下来是匹配行首后面的位置,要求此位置的后面不能是 .*helloworld 匹配的字符串,说白了要求此位置的后面不能是xxxxxxxxxxxxxxxxxxhelloworld 类似的字符串,这样就排除了从行首开始后面含有helloworld的情况了。

==================


我遇到的问题是匹配不含ipad、ipod、android的user-agent值,正确的正则为:
{user_agent_regex=^(?!.*ipad|.*ipod|.*android).*$}  注意:每个值前面都要加.*

附上以备参考:

(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 ‘\(’ 或 ‘\)’。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (|) 来组合一个模式的各个部分是很有用。例如, ‘industr(?:y|ies) 就是一个比 ‘industry|industries’ 更简略的表达式。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,’Windows (?=95|98|NT|2000)’ 能匹配 “Windows 2000″ 中的 “Windows” ,但不能匹配 “Windows 3.1″ 中的 “Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如’Windows (?!95|98|NT|2000)’ 能匹配 “Windows 3.1″ 中的 “Windows”,但不能匹配 “Windows 2000″ 中的 “Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

更多详情请查看:http://www.cnblogs.com/afarmer/archive/2011/08/29/2158860.html
阅读(1035) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~