正则表达式有两个重要概念:贪婪匹配和惰性匹配。贪婪匹配在进行匹配时的行为模式是多多益善,它们会尽可能地从一段文本的开头一直匹配到这段文本的末尾。相反,惰性匹配是适可而止,而不是从这段文本的开头碰到第一个匹配时为止。
问题
下面就是一个例子:
文本
我喜欢<B>
红色</B>
和<B>
黑色</B>
正则表达式
/<B>.*<\/B>/g
结果
我喜欢<B>红色</B> 和 <B>黑色</B>
这个例子里的原始文本来自一个Web页面,其中包含着两个HTML<B>
标签。而我们的任务是用一个正则表达式把那两个<B>
标签里的文本匹配出来(为了对这些文本进行替换或排版等)。
这个模式只找到了一个匹配而不是预期中的两个。第一个<B>
标签之后、最后一个</B>
标签之前的所有东西被 *
一网打尽。虽然没有漏掉我们想要匹配的文本,但问题是第2个<B>
标签不明不白地“失踪”了。
原因
为什么会这样?因为此处用到了*
,它和 +
都是所谓的“贪婪型”量词。
在不需要这种“贪婪行为”的时候该怎么办?答案是使用这些量词的“惰性”版本(“惰性在这里的含义是匹配尽可能少的字符,与“贪梦型”量词的行为模式刚好相反)。惰型量词的写法很简单,只要给贪婪型量词加上一个 ?
后缀即可。
解决办法
下面是使用 *?
来解决刚才那个例子的问题:
正则表达式
/<B>.*?<\/B>/g
结果
我喜欢<B>红色</B>
和 <B>黑色</B>
问题得到了圆满解决。因为使用了惰性 *?
,第一个匹配将仅限于红色,原始文本里的<B>
黑色</B>
成为了第二个匹配。
?
只能匹配零个或一个字符,{n} 和 {m,n} 也有一个重复次数的上限。换句话说,这几种语法所定义的“重复次数”都是有限的。而其他重复匹配语法(如*、+)在重复次数方面都没有上限值,而这样做有时会导致过度匹配的现象。
评论 (0)