匹配优先存在的问题,以及解决办法
1、匹配优先存在的问题,考虑下面的情况: The name "dumpling" is said "jiaozi" in Chenese. 我们想要匹配 双引号引起来的单词,这里也就是 dumpling和jiaozi。
使用 ".*" ,出现什么问题? "匹配第一个双引号,.* 量词优先匹配,一直吃下去,迟到最后的e,导致后面匹配失败(也就是全局匹配失败),因此要吐出来,一次吐出一个,尝试一下,失败了再吐出一个,直到jiaozi"后面的"匹配成功,return。 这当然不是我们预期的结果,怎么办?
2、这里错误的原因是,".*" 匹配了双引号的中的任意文本,这不是我们的意图,应该是匹配除了"之外的任意文本。那么我们使用 排除型字符组。如下:"[^"]*" ,注意排除型字符组的含义是:匹配一个字符,这个字符是除了"以外的任意字符。
3、现在考虑下面的场景:<B>Andy</B><B>Bill</B> ,要匹配<B></B>中的人名,我们使用 <B>[^</B>]*</B>,这存在问题:[^</B>]不是表示除了 "</B>"以外的字符,而是匹配一个字符,这个字符是除了 < / B >以外的字符,也就是说等价于 [^<>B/],[^</B>]*就是匹配任意多个字符,字符中不包含 < / B >。这不是我们的意图,怎么解决这个问题?
4、这里错误的原因是:量词匹配优先,也就是会多吃。我们知道正则表达式匹配过程中,会有回溯。对于量词,无论是匹配优先还是忽略优先,都要为全局匹配服务。当全局匹配失败的时候,都要回溯。对于匹配优先,多吃的要吐出来,对于忽略优先,少吃的再吃下去。解决办法是量词忽略优先,尽量少吃。如下:<B>.*?</B>。
5、还有没有其他的解决办法?
使用环视功能,如下: <B>((?!</?B>).)*</B> ,(?!<B>)是顺序环视,从左往右,匹配一个位置,这个位置的右边不是 <B> 或者 </B>。这个位置后面紧接着一个任意字符(注意:这个任意字符,已经是限制后的任意字符,前面的约束已经限定了 多个. 不能组成<B> 或者 </B>)。