建议43:使用exec增强正则表达式功能
RegExp对象定义了两个用于执行模式匹配操作的方法,它们的行为与String对象的正则表达式操作方法类似。例如,RegExp对象的exec方法与String对象的match方法相似,只不过exec是以字符串为参数的RegExp对象方法,而match方法是以正则表达式为参数的String对象方法。在非全局模式下,它们的返回值是相同的。
在所有RegExp模式匹配方法和String模式匹配方法中,exec方法的功能最强大。作为正则表达式的通用匹配方法,exec方法比RegExp.test()、String.search()、String.replace()和String.match()都复杂。该方法需要一个参数,用来执行要执行操作的字符串并返回一个数组,此数组中存放的是匹配结果。如果没有找到匹配的文本,返回值为null。例如:
var s = "javascript";
var r = /java/g;
var a = r.exec(s); //["java"]
exec方法的工作机制是这样的:当调用方法时,先检索字符串参数,从中获取与正则表达式相匹配的文本。如果找到了匹配的文本,就会返回一个数组;否则,返回null。对返回数组的元素的具体说明如下:
第0个元素,是与表达式相匹配的文本。
第1个元素,是与正则表达式的第1个子表达式相匹配的文本(如果存在)。
第2个元素,是与正则表达式的第2个子表达式相匹配的文本,依此类推。
返回数组还包含几个属性,具体说明如下:
length,该属性声明的是数组中的元素个数。
index,该属性声明的是匹配文本的第一个字符的位置。
input,该属性包含的是整个字符串。
当调用非全局模式的正则表达式对象的exec方法时,返回的数组与调用字符串对象的match方法返回的数组是完全相同的。
当执行全局匹配模式时,exec的行为就略有变化。这时它会定义lastIndex属性,以指定下一次执行匹配时开始检索字符串的位置。在找到了与表达式相匹配的文本之后,exec方法将把正则表达式的lastIndex属性设置为下一次匹配执行的第一个字符的位置。也就是说,可以通过反复地调用exec方法来遍历字符串中的所有匹配文本。当exec再也找不到匹配的文本时,将返回null,并且把属性lastIndex重置为0。
在下面的这个示例中,定义正则表达式直接量,用来匹配字符串s中每个字符。在循环结构的条件表达式中反复执行匹配模式,并将返回结果的值是否为null作为循环条件。当返回值为null时,说明字符串检测完毕。然后,读取返回数组a中包含的匹配子字符串,并调用该数组的属性index和lastIndex,其中index显示当前匹配子字符串的起始位置,而lastIndex属性显示下一次匹配操作的起始位置。例如:
var s = "javascript"; // 测试使用的字符串直接量
var r = /w/g; // 匹配模式
while((a = r.exec(s)) != null){ // 循环执行匹配操作
alert(a[0] + "\n" + a.index + "\n" + r.lastIndex); /* 显示每次匹配操作时返回的结果数组信息*/
}
实际上通过循环结构反复调用exec方法是唯一获得全局模式的完整模式匹配信息的方法。
无论正则表达式是否为全局模式,exec方法都会将完整的细节添加到返回数组中。字符串对象的match方法就不同,它在全局模式下返回的数组中不会包含这么多的细节信息。