2

零基础学习推荐: https://juejin.cn/post/6844903845227659271
正则表达式手册: http://tool.oschina.net/uploads/apidocs/jquery/regexp.html

1. 元字符汇总

image
image
image
image
image
分组与回溯引用:

元字符描述
(pattern)()会把每个分组里的匹配的值保存起来,从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推
(?:pattern)(?:) 表示非捕获分组,和捕获分组唯一的区别在于,非捕获分组匹配的值不会保存起来;
\1或\2等表示重复正则第一个(或第二个)圆括号内匹配到的内容

注: (?:pattern) 在使用 "或" 字符 (|) 来组合一个模式的各个部分很有用。例如,'industr(?:y|ies)' 就是一个比 'industry|industries'更简略的表达式。因为我们单独存储下 “y” 或者 “ies” 没有什么意义

2. 正则表达式在JS中的使用

2.1 基本用法

let reg1 = /asd/;
let reg2 = new RegExp("asd","g");//匹配方法 匹配模式

typeof /asd/;//object
/as/.test("asd");//true
/asd/.test("assd");//false

/asd/.exec("asd");
//["asd", index: 0, input: "asd", groups: undefined]
/asd/.exec("assd");//null

在exec中匹配到了就会返回一个数组对象,数组对象中第一项是第一个满足匹配得字符串,第二项得是满足匹配开始得下标。第三项是被匹配得输入。groups是命名捕获组。

2.2 配合字符串方法使用

字符串String具有matchreplacesearchsplit方法

"asd".match("as");//["as", index: 0, input: "asd", groups: undefined]
"asd".match(/as/);//["as", index: 0, input: "asd", groups: undefined]
//没有就是null
"asd".replace(/as/,"sa");// "sad" 不会改变原字符串,没匹配就不变
"asd".search(/dd/);//-1 返回第一个匹配得位置下标,没有就-1
"asd".search(/sd/);//1
"asd".split(/s/);//["a", "d"];

replace配合正则使用详解
replace()方法的第二个参数可以是一个文本,也可以是一个函数,在只有一个匹配项(即与模式匹配的字符串)的情况下,会向这个函数传递3个参数:模式的匹配项,模式匹配项在字符串中的位置和原始字符串。在正则表达式中定义了多个捕获组的情况下,传递给函数的参数依次模式的匹配项第一个捕获组的匹配项第二个捕获组的匹配项…,但最后两个参数仍然分别是模式的匹配项在字符串中的位置原始字符串

var toUrl = 'user/add?id=$18&t=update'.replace(/\$(\d+)/g, function (a, b, c, d) {
            console.log(a);  //$18,\$(\d+)匹配的模式匹配项
            console.log(b);     //18,(\d+)匹配的第一个捕获组的匹配项
            console.log(c);  //12,匹配项的位置
            console.log(d);  //user/add?id=$18&t=update,原始字符串
        });

replace第二个参数若是一个函数:

  1. 匿名函数执行多少次,取决于正则能在字符串中捕获多少次
  2. 每次执行匿名函数,arguments值和通过exec捕获到的内容很类似
  3. return 返回值就是需要去替换的内容

    var str = 'pku2016pku2017';
    str = str.replace(/(\d+)/g, function () {
     console.log(arguments);
     // 第一次执行: ["2016", "2016", 7, "pkusoft2016pkusoft2017"]  
     //数组中各项解释:[正则匹配项,()中匹配的项,位置,原str]
     // 第二次执行: ["2017", "2017", 18, "pkusoft2016pkusoft2017"]
     // 返回的数组和执行exec返回的结果一致
    return '0000';
    });
    console.log(str); // pkusoft0000pkusoft0000

    3. 其它

3.1 命名组

具名组匹配在圆括号内部,在模式的头部添加问号尖括号和组名,就可以在exec方法上返回结果的groups上找到该组名。

let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
"1999-01-24".match(reg) //注意groups
"1999-01-24".replace(reg, "$<day>-$<month>-$<year>")//"24-01-1999"

3.2 全局匹配模式的状态记录

首先,要明确一点,所有的正则表达式都有一个lastIndex属性,用于记录上一次匹配结束的位置。如果不是全局匹配模式,那lastIndex的值始终为0,在匹配过一次后,将会停止匹配。

正则表达式的全局匹配模式,就是在创建正则表达式的时候使用g标识符或者将global属性设置为true,在全局匹配模式下,正则表达式会对指定要查找的字符串执行多次匹配。每次匹配使用当前正则对象的lastIndex属性的值作为在目标字符串中开始查找的起始位置。如果找不到匹配的项lastIndex的值会被重新设置为0。

看下面的例子:

var regex = /abc/g;
var str = '123#abc';
console.log(regex.lastIndex);   // 0
console.log(regex.test(str));   // true
console.log(regex.lastIndex);   // 7
console.log(regex.test(str));   // false
console.log(regex.lastIndex);   // 0
console.log(regex.test(str));   // true
console.log(regex.lastIndex);   // 7
console.log(regex.test(str));   // false

进阶题:

function captureOne(re, str) {
  var match = re.exec(str);
  return match && match[1];
}
var numRe  = /num=(\d+)/ig,
    wordRe = /word=(\w+)/i,
    a1 = captureOne(numRe,  "num=1"),
    a2 = captureOne(wordRe, "word=1"),
    a3 = captureOne(numRe,  "NUM=2"),
    a4 = captureOne(wordRe,  "WORD=2");
[a1 === a2, a3 === a4]

答案是: [true, false]

3.3 常用正则表达式

// 匹配时间
let time = '2008-12-04 18:00:00'
const timeReg = /(?<year>\d{4})-(?<month>\d{2})-(?<date>\d{2}) (?<hour>\d{2}):(?<minute>\d{2}):(?<second>\d{2})/
const { year, month, date, hour, minute, second } = timeReg.exec(time).groups

// 匹配ip
const ipRegExp =
/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/;

小飞2020
18 声望4 粉丝

相信自己, 慢慢变强