JS中exec,match,replace,test方法对比

时间:2022-01-28 18:36:48

正则表达式中各种方法的用法和比较(更多信息参考)

RegExp的exec方法总结:

(1)第0个元素是与表达式匹配的文本

(2)第1个元素是与子表达式匹配的文本,捕获组

(3)很显然返回值是数组

(4)返回数组有length,index(匹配文本第一个字符位置),input(整个字符串)属性

                              var rts = /([?&])_=[^&]*/;
				var cacheURL="http://localhost:8080/qinl/xx.action?_=me";
				var result=rts.exec(cacheURL);
				console.log(result);
通过 该图,你会发现返回的元素个数是2,同时有index属性表示开始匹配的下标,input表示传入正则表达式的字符串!

(5)非全局的正则执行exec和match方法完全一致!

                              var rts = /([?&])_=[^&]*/;
				var cacheURL="http://localhost:8080/qinl/xx.action?_=me";
				var result=rts.exec(cacheURL);
				console.log(result);//一样
				var result1=cacheURL.match(rts);
				console.log(result1);//一样
通过 该图,你会发现非全局的正则表达式exec和match的结果完成一样!

(6)当全局正则执行exec时候会有lastIndex属性表示下一次搜索下标,当exec再也找不到匹配的文本时候返回null,并且把lastIndex重置为0

String对象的test方法:

(1)使用正则表达式字面量和RegExp构造函数创建的正则表达式不一样,在ECMAScript3中,字面量始终共享同一样RegExp实例,而构造函数创建的每一个新的RegExp都是一个新实例。ECMA5中相同
(2)source属性中保存的是规范形式的字符串,也就是字面量形式的字符串。同时还包含global,multiline,lastIndex,ignoreCase属性!
(3)在IE中即使在非全局模式下,lastIndex也会一直变化!
(4)RegExp的toLocalString和toString都会返回正则表达式的字面量,与创建方式无关!
(5)正则表达式的valueOf返回正则表达式本身!
(6)正则表达式的长属性名和短属性名可以从exec和test方法中取出更具体的信息,但是Opera不支持短属性名!
(7)可以通过RegExp.$1访问第一个捕获组,依次类推,可以用于test,exec方法等
(8)input($_)表示最近一次要匹配的字符串,lastMatch($&)最近一次的匹配项,leftContext($`)表示lastMatch之前的文本,rightContext($')lastMatch右边的文本,multiline是否支持多行匹配!lastParen($+)最近一次的捕获组。Opera只支持leftContex和rightContext
IE不支持multiline属性!

String对象的replace方法:

(1)第一个参数表示执行匹配的正则表达式,也可以传递字符串,第二个参数表示准备代替匹配的字符串,也就是用第二个参数替换第一个参数的内容!
(2)replace方法不会把字符串转为正则表达式,而是以字符串直接量的文本模式进行匹配,第二个参数可以是替换的文本,或者生产匹配文本的函数!
(3)如果正则表达式具有全局性质那么就会替换所有的匹配字符串,否则只是替换第一个匹配字符串

(4)replace方法传入的第一个形参是每次匹配的文本,接着$2….$n是捕获组的值,接着的形参是匹配文本的下标,接着的形参是要执行匹配的字符串,也就是调用replace方法的字符串,一直不变!

          var s='script language="javascript" type=" text/javascript "';
		   var f=function($1)
		   {
		      return $1.substring(0,1).toUpperCase()+$1.substring(1);
		   }
		   //对每一个单词都作用单独处理\b表示单词边界,而且是全局的!
		   //传入第二个函数的参数顺序是:每次匹配的文本(这里是单词),然后顺次是捕获组的值,然后是匹配字符在下标中的位置
		   //最后一个参数表示字符串本身!
		   var a=s.replace(/(\b\w+\b)/g,f);
		   //打印Script Language="Javascript" Type=" Text/Javascript "
		   console.log(a);
这个例子实现了所有单词的首字母大写,但是没有完全利用正则表达式给我们传入的所有的参数,所以我们可以做下面的修改:

                 var f=function($1,$2,$3)
		   {
		      return $2.toUpperCase()+$3;
		   }
		   //对每一个单词都作用单独处理\b表示单词边界,而且是全局的!
		   //传入第二个函数的参数顺序是:每次匹配的文本(这里是单词),然后顺次是捕获组的值,然后是匹配字符在下标中的位置
		   //最后一个参数表示字符串本身!
		   var a=s.replace(/\b(\w)(\w*)\b/g,f);
		   console.log(a);
这时候我很好奇,如果是match会是怎么的

                 var s='script language="javascript" type=" text/javascript "';
		   var result=s.match(/\b(\w)(\w*)\b/g);
		   //打印["script", "language", "javascript", "type", "text", "javascript"]
		   console.log(result)
下面我们给出match和exec的区别:

 表1:(match和exec方法的区别)

  全局(g) 非全局
有捕获组 (1)exec返回的数组只包含第一个匹配字符串和捕获组的数据,如果多次调用,那么会通过lastIndex不断返回新的结果
(2)match返回所有的匹配的结果,不包含捕获组,捕获组通过$n访问
(1)match和exec方法一样只是返回第一个匹配字符串和捕获组
无捕获组 (1)exec只返回第一个匹配元素,match返回所有的匹配元素
(2)如果多次在该RegExp中调用exec方法,那么会返回新的结果!
(1)match和exec方法一致,只是返回第一个匹配字符串组

         note:非全局下matchexec一样。全局模式下,exec只是包含第一个匹配字符串和捕获组,match返回的是所有匹配的结果!

例1:(阅读点击打开链接

通过循环结构反复调用exec是唯一获得全局模式的完整模式匹配信息的方法,无论正则表达式是否为全局模式,exec都会将完整的信息添加到返回数组中。字符串对象的match方法就不同,它在全局模式下返回的数组不包括那么多细节信息!

vars="java";
var r=/\w/g;
while((a=r.exec(s))!=null)
{
//a.length是1,a[0]就是每次匹配的一个字符,index就是匹配文本第一个字符的位置,input包含的是整个字符串
//a.input每次打印的都是一样的,结果是"java"
//a[0]第一次打印j,第二次为a,第三次是v,第四次是a
//a.index第一次打印0,第二次是1,第三次是2,第四次是3
 alert(a.length+"\n"+a[0]+"\n"+a.index+"\n"+r.lastIndex+"\n"+a.input);
}

注意:如果把上面的正则表达式的g去掉,那么就不会有lastIndex,于是每次打印的结果都是一样的,为[1,"j",0,0,"java"]。通过该图你就会发现全局模式下的exec保存的所有的信息!

例2:(正则表达式的贪婪和懒惰用法)

var s="abcd-abcd-abcd";
var reg=/(abcd-?)*/;
var result=s.match(reg);
//打印[abcd-abcd-abcd,abcd]其中问号表示出现0次或者1次,尽量少次数!
alert(result);

//(1)首先匹配"<"
//(2)直接匹配"html"字符串
//(3)直接绕过(\s)*?匹配字符">",最后首先得到的字符就是"<html>"
//(4)然后依次扩展前面的*?表达式!
//总结:*?是懒惰匹配,所以在第一次匹配的时候直接绕过他匹配下面的字符!
var s1="<html>< html><html >< html ></html>< /html></ html>< / html ><///html>";
var reg1=/<([\/\s]*?)html(\s)*?>/g;
alert(s1.match(reg1));

//打印[<p>title<p>,<h1>text<h1>]
//在同一个正则表达式的后面可以用\n引用前面的第n个捕获组的结果,记住:这里是结果不是前面的正则表达式模式!
//而是匹配的结果,如果要用前面的模式就要把前面的正则表达式重新书写一次。同时因为子表达式可以嵌套在其它子表达式中,因此他的位置编号是根据左边括号的顺序来编号的!
var s2="<h1>titile<h1><p>text<p>";
var reg2=/(<\/?\w+>).*\1/g;
alert(s2.match(reg2));

//实现数字和字母的顺序颠倒
var s3="aa11bb22c3d4e5f6";
var reg3=/(\w+?)(\d+)/g;
alert(s3.replace(reg3,"$2$1"));