正则表达式中各种方法的用法和比较(更多信息参考)
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);
(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);//一样
(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);
- 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)
表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方法就不同,它在全局模式下返回的数组不包括那么多细节信息!
- 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"));