利用正則表達式排除特定字符串
本文转载自:http://www.cnblogs.com/wangqiguo/archive/2012/05/08/2486548.html
查找不以baidu开头的字符串
baidu.com
sina.com.cn
正则:^(?
!baidu).*$ 匹配结果就是第2行。也就是第1行被排除了
这里使用了零宽度断言(?!exp),注意。我们有一个向前查找的语法(也叫顺序环视) (?=exp)
(?=exp) 会查找exp之前的【位置】假设将等号换成感叹号。就变成了否定语义,也就是说查找的位置的后面不能是exp
普通情况下?
!要与特定的锚点相结合,比如^行开头或者$行结尾,那么上面的样例的意思例如以下:
^(?!baidu).*$ 先匹配一个行开头的位置,而且要求接下来的位置的后面不是baidu这个字符串。这样由于第一行^之后的位置后面是baidu所以匹配失败,被排除在外了。
查找不以com结尾的字符串
www.sina.com.cn
www.educ.org
www.hao.cc
www.baidu.com
www.123.com
正则 ^.*?
(?<!com)$ 匹配前3行结果。
假设查找以com结尾的字符串则使用正则 ^.*?(?
<=com)$或者 ^.*?
com$
对正則表達式的解释:^.*?(?
<!com)$
首先匹配行开头,然后是 .*? 这个是忽略优先,也就是优先忽略不匹配不论什么字符,(?<!com) 这个是一个逆序环视的否定形式。意思是匹配一个位置此位置的前面不能是字符串com。最后是一个行结束。
对于www.123.com来说。首先匹配行首。接着匹配w后面的位置,发现前面不是com。所以成功但紧接着要匹配行尾。失败,回溯让.*? 匹配一个w符号。接着(?
<com)匹配第二个w后面的位置。发现前面也不是com匹配成功,紧接着要匹配$相应的行尾失败,一直到.*?匹配了www.baidu.com的时候。此时(?
<!com)匹配m后面的位置,此时此位置的前面是com匹配直接失败,接着.*?匹配行末尾,(?<!com)匹配$后面的位置。显然这次也失败了。所以整个全局匹配都失败。 www.123.com被排除到匹配之外。
这里的.*后面加不加问号结果都一样。
查找不含有if的行
if (a>b)
printf("hello");
else if(a<b)
printf("hello2");
else
printf("hello3");
正则 ^([^f]|[^i]f)+$
事实上这个匹配也是一个排除型字符串的匹配,可是不同于上面两种,由于这里的if可能既不在行开头,也不在行结尾。而是在字符串中间这样就给匹配带来了麻烦。在正則表達式中没有提供相似排除的功能。我们最easy想到的就是以下的正则:
^[^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的情况了。