非捕获性分组释疑

在看人民邮电出版社出版的《JavaScript高级程序设计》
看到7.3.4 非捕获性分组这里,书上说非捕获性分组不会创建反向引用,下面是例子:

var sToMatch = "#123456789";
var reNumbers = /#(?:\d+)/;
reNumbers.test(sToMatch);
alert(RegExp.$1);

 

这里alert输出是空的。

到了第8章,又出现了类似以下的代码:

var sToMatch = "en-us rv:0.9.4";
var reNumbers = /rv:(\d+\.\d+(?:\.\d+)?)/;
var result = reNumbers.test(sToMatch);
alert(RegExp.$1);

 

这里alert输出就成了0.9.4
最后那个.4是非捕获性分组捕获到的
这里就奇怪了,为什么前面的非捕获性分组不能捕获,而嵌套的非捕获性分组就又可以捕获了?
而且这里好像不用非捕获性分组照样可以达到相同的目的,为什么要用非捕获性分组呢?

 

 

 

要了解非捕获组就要先了解捕获组,之后再了解为什么会有非捕获组的出现
简单点说,捕获组就是把(Expression)中匹配到的内容保存到一个按“(”出现的顺序编号的组里,以供后续引用,引用的方式有反向引用,或是RegExp.$number等方式,不同的语言,支持的引用方式不同
只要使用了(),默认为使用了捕获组,而这就带来一个问题,有些场景不得不使用(),但又不关心它匹配到的内容,比如写一个匹配24小时制HH:mm:ss的时间的正则如下
([01][0-9]|2[0-3])(:([0-5][0-9])){2}
通常关心的只是整体的时间,并不关心局部的内容,这样就产生了一种副作用,将不关心的内容单独保存到内存中,只会浪费资源,降低效率
非捕获组就是为了抵消这一副作用来产生的,非捕获组只参与匹配,但不会把匹配到的内容捕获到组里

所以非捕获组根本就不参与编号,也就无从谈起它对应哪个$number
在取不存在的编号的捕获组时,有些语言会返回空字符串,有些语言会报异常

(\d+\.\d+(?:\.\d+)?)中,整体是一个捕获组,按“(”出现的顺序,编号为1,(?:\.\d+)虽然是非捕获组,也是要参与匹配的,只是不将匹配结果单独保存到组里而已

还需要说明的是,在绝大多数语言中,正则表达式整体对应的是$0,捕获组的编号是从1开始的

在有些语言中,还支持(?<name>Expression)的命令捕获组语法,所以有以下两种语法属于捕获组
(Expression)
(?<name>Expression)
其余的(?...)之类的语法定义的字符序列都不属于捕获组

posted @ 2014-06-11 15:13  大脸  阅读(451)  评论(0编辑  收藏  举报