正则表达式

如何创建正则表达式

  • 字面量创建var r = /a/;
  • 通过构造函数var r = new RegExp("a");

正则表达式实例属性及方法

  • 三个修饰符属性,只读不可修改
  • RegExp.prototype.ignoreCase
    正则表达式是否添加了忽略大小写的修饰符,返回一个布尔值

    var r = /asd/i;
    console.log(r.ignoreCase);    //true
  • RegExp.prototype.global
    正则表达式是否添加了全局匹配的修饰符,返回一个布尔值

    var r = /asd/i;
    console.log(r.global);    //true    
  • RegExp.prototype.multiline
    正则表达式是否添加了换行的修饰符,返回一个布尔值

    var r = /asd/m;    
    console.log(r.multiline);    //true    
  • RegExp.prototype.lastIndex
    返回一个整数,表示正则表达式下一次开始匹配的位置,

    var s = "wqerqt";
    var r = /q/g;
    console.log(r.lastIndex);   //0
    console.log(r.test(s));     //true
    console.log(r.lastIndex);   //2
    console.log(r.test(s));     //true
  • RegExp.prototype.source
    返回正则表达式的字符串形式;即不包括首尾的/
  • 两个实例方法
  • RegExp.prototype.test()
    作用是否能匹配参数字符串,返回一个布尔值

    console.log(/as/.test("fdas"));   //true
    console.log(/as/.test("fd"));   //false

    test()方法在全局g的匹配下,会记录上一次test()后开始的位置,来进行下一次test();
    可以这么来理解lastIndex用来指定test()开始的位置,lastIndex只对同一个正则表达式有连续有效的作用,例如重新创建正则表达式,会一直返回true或者false

    var i = 3,
        r = /as/g;
    while(i) {
        console.log(r.test("asd"));
        i --;
    }                          //true false true

    下面三种结果相同都是true,相当于新的正则表达式在匹配字符串,只是正则表达式是一样的

    var i = 3,
    while(i) {
        //r = new RegExp("as","g");
        //r = /as/g;    
        console.log(/as/g.test("asd"));
        i --;
    }                          //true true true
    

    所以个人认为在外部定义正则表达式,内部引用会好点

  • RegExp.prototype.exec()
    作用是返回一个数组,成员是匹配成功的字符串,否则返回null
    但是数组的长度是组匹配数再加1,例如下面例子的,数组长度只有1

    var r = /as/g;
    console.log(r.exec("asdas"));   //["as", index: 0, input: "asdas", groups: undefined]
    console.log(r.exec("asdas"));   //["as", index: 3, input: "asdas", groups: undefined]
    console.log(r.exec("adsd"));    //null

    返回数组结果还有两个属性:
    index:返回匹配时的位置
    input:返回参数字符串

    var r = /as/g;
    var arr = r.exec("asdas");
    console.log(arr.index, arr.input);     //0,"asdas"
    var arr1 = r.exec("asdas");
    console.logarr1.index, arr1.input);   //3,"asdas"    

匹配规则

详情可看MDN文档

几个值得记忆的点:

(.):任意字符,除了\r\n\\u2028\u2029的所有单个字符,大于\u0xFFFF的两个字符也不行
[\s\S]与[^]:所有单个字符,包括换行符
o\\bo:不存在这样的单词进行匹配
+:{1,+Infinity},取尽可能大,+?则是取尽可能小,最小为1
*:{0,+Infinity},取尽可能大,*?则是取尽可能小,最小为0
?:{0,1},取尽可能大,最大为1,??则是取尽可能小,最小为0
[xyz]:单个字符是x或y或z;而[^xyz],则是除了xyz的单个字符

组匹配

就是用来捕获自己想要的值,用来自己进行后续操作

var a = /-(\w)/g;
console.log('get-own-property-name'.replace(a,function (match, $1) {
    return $1.toUpperCase();
}));                     //getOwnPropertyName

match:匹配成功的字符串
$1:是第一个组匹配的值,例如后面多个括号则是$2$3...
注意组匹配嵌套时的顺序console.log("bc".replace(/((b)c)/g,"$1+$2")); //bc+b从左开始,而不是从内开始
字符串的match与split在进行组匹配时,是否添加修饰符g结果不一样

console.log("abc".match(/(.)b/g));   //["ab"]
console.log("abc".match(/(.)b/));    //(2) ["ab", "a", index: 0, input: "abc", groups: undefined]
console.log("abc".split(/(b)/));     // ["a", "b", "c"]
console.log("abc".split(/b/));       //["a", "c"]

总结:match方法只要进行了g全局匹配就只会返回最终匹配到的字符串组成的数组;split只要进行了组匹配就会返回捕获的内容

  • 非捕获组
    ?:表示;说直白点就是:还是这么匹配但是我不返回括号里的内容,所以我们进行split的组匹配时可以进行修改console.log("abc".split(/(?:b)/)); //["a", "c"]
  • 先行断言
    x(?=y)表示,意思是匹配一个x,x必须在y前面,结果中不返回y
  • 先行否定断言
    x(?!y)表示,意思是匹配一个x,x后面不能是y,结果中不返回y
  • 后行断言
    (?<=y)x表示,意思是匹配一个x,x前面必须是y,结果中不返回y
  • 后行否定断言
    (?<!=y)x表示,意思是匹配一个x,x前面不能是y,结果中不返回y

    console.log(/(?<!=b)a/.exec("bcaba"));  //["a", index: 2, input: "bcaba", groups: undefined]
    console.log(/(?<=b)a/.exec("bcaba"));   //["a", index: 4, input: "bcaba", groups: undefined]

经典例子:

数字格式化:

var r = /\B(?=((\d{3})+$))/g;
console.log('1234567890'.replace(r, '.'));    //1.234.567.890
console.log('123'.replace(r, '.'));           //123

Infinity
293 声望9 粉丝

学前端中,只想激情优雅的写代码