js-贪婪和惰性匹配

1.贪婪匹配(greedy)

它会匹配尽可能多的字符。它首先看整个字符串,如果不匹配,对字符串进行收缩;遇到可能匹配的文本,停止收缩,对文本进行扩展,当发现匹配的文本 时,它不着急将该匹配保存到匹配集合中,而是对文本继续扩展,直到无法继续匹配 或者 扩展完整个字符串,然后将前面最后一个符合匹配的文本(也是最长的)保存起来到匹配集合中。所以说它是贪婪的。

光看上面的定义,我们很难有一个生动的认识,现在假设我们要匹配下面 <b>和</b> 之间的文本。为了做演示,尽管不符合 HTML 的定义,我们再加入一段<b>和</c>之间的文本:

nowamagic.net is a <b>good</b> website to <b>learn</b> IT <b>skills</c>.

1 <b>.*</b>
效果演示
nowamagic.net is a good website to learn IT skills.


本例代码
1 function reg_replace()
2 {
3     var test = document.getElementById("test");
4     aim = "<b>.*</b> ";
5     var regex = new RegExp("("+aim+")","g");
6     test.innerHTML = test.innerHTML.replace(regex,"<span style='background-color:orange'>$1</span>");
7 }

这样匹配显然不是我们的初衷,它仅找到了一个匹配,而通常情况下,我们希望得到的是<b>junior</b> 和 <b>living</b> 两个匹配。

贪婪匹配的匹配过程



01 //不匹配,收缩
02 nowamagic.net is a <b>good</b> website to <b>learn</b> IT <b>skills</c>.
03 //不匹配,收缩
04 owamagic.net is a <b>good</b> website to <b>learn</b> IT <b>skills</c>.
05 //不匹配,收缩
06 wamagic.net is a <b>good</b> website to <b>learn</b> IT <b>skills</c>.
07 ...   //中间略
08 // 找到可能匹配的,扩展
09 <span style="background-color:orange"><</span>b>good</b> website to <b>learn</b> IT <b>skills</c>.
10 // 找到可能匹配的,扩展
11 <span style="background-color:orange"><b</span>>good</b> website to <b>learn</b> IT <b>skills</c>.
12 // 找到可能匹配的,扩展
13 <span style="background-color:orange"><b></span>good</b> website to <b>learn</b> IT <b>skills</c>.
14 ...   //中间略
15  //找到一个匹配,但是并不保存到结果集中,而是继续进行扩展
16 <span style="background-color:orange"><b>good</b></span> website to <b>learn</b> IT <b>skills</c>.
17 <span style="background-color:orange"><b>good</b> </span>website to <b>learn</b> IT <b>skills</c>.
18 // 找到可能匹配的,扩展
19 <span style="background-color:orange"><b>good</b> website to <b>learn</b></span> IT <b>skills</c>.
20 //字符串结束,将前面找到的最后一个匹配 <b>good</b> website to <b>learn</b> 保存到匹配结果集中


2.惰性匹配


惰性匹配(lazy)

它会匹配尽可能少的字符,它从第一个字符开始找起,一旦符合条件,立刻保存到匹配集合中,然后继续进行查找。所以说它是懒惰的。

还是这个例子:

nowamagic.net is a <b>good</b> website to <b>learn</b> IT <b>skills</c>.

1 <b>.*</b>
效果演示
nowamagic.net is a good website to learn IT skills.


本例代码
1 function reg_replace()
2 {
3     var test = document.getElementById("test");
4     aim = "<b>.*</b> ";
5     var regex = new RegExp("("+aim+")","g");
6     test.innerHTML = test.innerHTML.replace(regex,"<span style='background-color:orange'>$1</span>");
7 }

这样匹配显然不是我们的初衷,它仅找到了一个匹配,而通常情况下,我们希望得到的是<b>good</b> 和 <b>learn</b> 两个匹配。

解决的办法,就是上面说到的惰性匹配,它的语法如下表所示:

贪婪匹配 惰性匹配 匹配描述
? ?? 匹配 0 个或 1 个
+ +? 匹配 1 个或多个
* *? 匹配 0 个或多个
{n} {n}? 匹配 n 个
{n,m} {n,m}? 匹配 n 个或 m 个
{n,} {n,}? 匹配 n 个或多个

对于本例,当我们再使用惰性匹配。

1 <b>.*?</b>
效果演示
nowamagic.net is a good website to learn IT skills.


惰性匹配的匹配过程
01 n   // 不匹配,继续
02 no  // 不匹配,继续
03 ...  // 中间略
04 nowamagic.net is a <span style="background-color:orange"><</span>    // 找到可能匹配的字符,继续
05 nowamagic.net is a <span style="background-color:orange"><b</span>   // 找到可能匹配的字符,继续
06 ...  // 中间略
07 //找到匹配,保存到结果集中,继续进行剩下的文本。
08 nowamagic.net is a <span style="background-color:orange"><b>good</b></span> website to <b>learn</b> IT <b>skills</c>.
09 w   // 不匹配,继续
10 we  // 不匹配,继续
11 website to <span style="background-color:orange"><</span>        // 找到可能的匹配,继续  
12 website to <span style="background-color:orange"><b</span>   // 找到可能的匹配,继续
13 ...  // 中间略
14 //找到匹配,保存到结果集中,继续进行剩下的文本。
15 website to <span style="background-color:orange"><b>learn</b></span>
16 I   //不匹配,继续
17 IT  //不匹配,继续
18 IT <span style="background-color:orange"><</span>    // 找到可能的匹配,继续
19 IT <span style="background-color:orange"><b</span>   // 找到可能的匹配,继续
20 ...  // 中间略
21 IT <span style="background-color:orange"><b>skills</</span>c>.  // 匹配失败,继续找
22 IT <b>skills</c>.   // 不匹配,继续
23 // 字符串结束,匹配结束。一共找到了两个匹配<b>good</b>和<b>learn</b>
24 IT <b>skills</c>.

我们回顾一下上面 “\d{1,3}” 匹配数字的例子,对于“1234”,当我们使用“\d{1,3}”时,进行的是贪婪匹配,它首先找到“123”(因为“1234”不符合),之后的“4”也符合,所以,找到的匹配是“123”和“4”。

当我们使用“\d{1,3}?”匹配上面的例子,对于“1234”,这次是惰性匹配。首先,发现“1”符合,将“1”保存到匹配集合中;随后,依次发现“2”、“3”、“4”符合,并依次保存到结果集中,最后,我们得到了四个匹配“1”、“2”、“3”、“4”。 


from blog:www.nowamagic.net/librarys/veda/detail/1038


转载于:https://my.oschina.net/lgmcolin/blog/85216

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值