您的位置:首页 > Web前端 > JavaScript

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

2016-12-09 17:24 435 查看
正则表达式中各种方法的用法和比较(更多信息参考)
RegExp的exec方法总结:
(1)第0个元素是与表达式匹配的文本
(2)第1个元素是与子表达式匹配的文本,捕获组
(3)很显然返回值是数组
(4)返回数组有length,index(匹配文本第一个字符位置),input(整个字符串)属性

[javascript]
view plain
copy

                          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方法完全一致!

[javascript]
view plain
copy

                          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方法的字符串,一直不变!

[javascript]
view plain
copy

     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);  

这个例子实现了所有单词的首字母大写,但是没有完全利用正则表达式给我们传入的所有的参数,所以我们可以做下面的修改:

[javascript]
view plain
copy

            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会是怎么的

[javascript]
view plain
copy

            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:非全局下match和exec一样。全局模式下,exec只是包含第一个匹配字符串和捕获组,match返回的是所有匹配的结果!
例1:(阅读点击打开链接
通过循环结构反复调用exec是唯一获得全局模式的完整模式匹配信息的方法,无论正则表达式是否为全局模式,exec都会将完整的信息添加到返回数组中。字符串对象的match方法就不同,它在全局模式下返回的数组不包括那么多细节信息!

[javascript]
view plain
copy

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:(正则表达式的贪婪和懒惰用法)

[javascript]
view plain
copy

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")); 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: