分类
Javascript

正则表达式中使用贪婪惰性匹配

正则表达式有两个重要概念:贪婪匹配和惰性匹配。贪婪匹配在进行匹配时的行为模式是多多益善,它们会尽可能地从一段文本的开头一直匹配到这段文本的末尾。相反,惰性匹配是适可而止,而不是从这段文本的开头碰到第一个匹配时为止。

下面就是一个例子:

文本

我喜欢<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}也有一个重复次数的上限。换句话说,这几种语法所定义的“重复次数”都是有限的。而其他重复匹配语法(如*、+)在重复次数方面都没有上限值,而这样做有时会导致过度匹配的现象。