正则表达式-逻辑”非“处理(记录)

“非”是正则表达式中最难处理的逻辑关系。因为没有直接对应的结构,“非”的处理比较吃力。

  最简单的“非”,意思是此处不能出现某个字符,这一点通常很直观,似乎用排除型字符组『[…]』就可以解决。比如双引号字符串的匹配,首尾两个双引号很容易匹配,其中的内容肯定不是双引号(暂时不考虑转义的情况),所以可以用『[“]』表示即可,其长度不确定,所以用来限定,所以整个表达式就是『”[^”]“』,非常简单。

  但是,事情果真都如此简单吗?我们仍然举cat和cut的例子,如果仍然希望匹配c开头、t结尾的单词,但不希望匹配cut,可以写成『c[^u]t』,是否就可以了?

  这个表达式的意思是:最开头的字母是c,之后是一个不为u的字符,之后是t。没错,它确实不会匹配cut,也可以匹配cat。但是,chart、conduct、court等等,它也没法匹配,因为[^u]的意思是:匹配一个不是u的字符。

  那么,把『[u]』改成『[u]+』好了,这样应该就可以解决问题了。但是真的如此吗?『[u]+』的意思是,一个或若干(最多到无穷)个字符,但每一个字符都不能是u。所以,尽管『c[u]+t』能匹配cat和chart,却不能匹配conduct和court。

  看来,“非”真是比较难对付,让人非常纠结。好在,也不是没有办法解决它。回复到与-或-非的观点,分析要实现的功能:

逻辑关系 分析
以c开头,以t结尾
c和t之间可以出现的字母必须多于一个,没有上限
c和t之间不能只有一个字符u

  如果只考虑“与”和“或”两个逻辑,表达式很好写,是『c[a-z]+t』,再把剩下的条件附加上去,就可以解决问题了。我们仔细看“非”的条件:c和t之间不能只有一个字符u。既然『[^u]+』表达的并不是这个意思,我们不妨换一种表述法:在c之间的位置向后看,不能出现cut。这一点,正好对应否定顺序环视(positive look-ahead)功能,『(?!cut)』就是用来进行这种判断的,它判断之后的字符串能不能由cut匹配,但并不真正真正进行匹配,也不会移动“当前位置”。所以我们将它放在表达式的最开头,得到『(?!cut)c[a-z]+t』。这个表达式的逻辑是:只有在当前位置右侧字符串不能由cut匹配的情况下,才从这里开始,向右尝试用c[a-z]+t。

  如果我们更进一步,需要排除掉cat和cut,可以把否定顺序环视改为『(?!c[au]t)』。这样就能保证,匹配到的肯定不是cat或者cut。

  更复杂一点,如果我们要验证这样一个字符串:它全部由小写字母构成,长度不超过12位,其中不能包含unfavored或者unwanted。也可以照章处理,先匹配“长度不超过12位”的小写字母『[a-z]{,12}』,然后写出匹配“不需要匹配内容”的正则表达式,『(unfavored|unwanted)』,再用否定顺序环视将它“排除”即可,只是这次要注意,不能直接写『(?!(unfavored|unwanted))』,因为它只能排除『(unfavored|unwanted)』出现在字符串开头的情况,为了排除它出现在字符串中的情况,我们要把否定顺序环视改为『(?![a-z](unfavored|unwanted))』,这样就确保完整的“排除”,整个表达式就是『(?![a-z](unfavored|unwanted))[a-z]{,12}』。

  总结一下,正则表达式中的“非”,除去能用排除型字符组直接表示的,复杂一点的“非”逻辑都是按照这样的思路进行的:先用一个正则表达式准确匹配需要“排除”的字符串,再用环视功能排除掉它——“非”确实是正则表达式中,最难处理的逻辑关系,好在它并不复杂,而且,除去一些比较古老的工具(比如Apache 1.3),现在各种工具和语言,基本都支持这种功能。

参考链接:

https://kb.cnblogs.com/page/96414/

原文地址:http://www.cnblogs.com/jianmuzi/p/16795491.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性