js知识梳理九

正则捕获

把一个字符串中和正则匹配的部分获取到

正则

  • exec
  • test

字符串

  • replace
  • split
  • match

基于EXEC可以实现正则的捕获

  1. 如果当前正则和字符串不匹配,捕获的结果是NULL
  2. 如果匹配,捕获的结果是一个数组
    • 0:大正则捕获的内容
    • index:正则捕获的起始索引
    • input:原始操作的字符串
  3. 执行一次EXEC只能捕获到第一个和正则匹配的内容,其余匹配的内容还没有捕获到,而且更恶心的是,我傻傻的执行多次,然而并没啥卵用 =>“正则的捕获有懒惰性”:只能捕获到第一个匹配的内容,剩余的默认捕获不到
  4. 解决正则捕获的懒惰性,我们需要加全局修饰符G(这个是唯一的方案,而且不加G不管用什么办法捕获,也都不能把全部匹配的捕获到)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     let str = 'zhufeng2018peixun2019';
    let reg = /\d+/;

    console.log(reg.exec('zhufengpeixun'));//=>null
    console.log(reg.exec(str));//=>['2018',index:7,input:...]

    //=>LAST-INDEX不变导致了正则捕获的懒惰性
    console.log(reg.lastIndex);//=>0 正则捕获时候,下一次在字符串中开始查找的索引
    console.log(reg.exec(str));//=>['2018']
    --------------------------------------------------------
    //=>即使我们手动修改了LAST-INDEX,然而还是没用
    console.log(reg.exec(str));//=>['2018']
    reg.lastIndex = 11;
    console.log(reg.lastIndex);
    console.log(reg.exec(str));//=>['2018']

    // 需要正则表达式加上全局匹配符 ‘g’
    // let str = 'zhufeng2018peixun2019';
    // let reg = /\d+/g;
    // console.log(reg.lastIndex);//=>0
    // console.log(reg.exec(str));//=>['2018']
    // console.log(reg.lastIndex);//=>11
    // console.log(reg.exec(str));//=>['2019']
    // console.log(reg.lastIndex);//=>21
    // console.log(reg.exec(str));//=>null
    // console.log(reg.lastIndex);//=>0
    // console.log(reg.exec(str));//=>['2018']

?在正则中的作用

  1. 量词元字符:出现零次或者一次
    • /-?/ 让减号出现一次或者不出现
  2. 取消贪婪性
    • /\d+?/ 捕获的时候只捕获最短匹配的内容
  3. ?: 只匹配不捕获
  4. ?= 正向预查
  5. ?! 负向预查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 let str = 'zhufeng2018peixun2019';
let reg = /\d+/g;
console.log(reg.test(str));//=>TRUE
console.log(reg.lastIndex);//=>11 基于TEST进行匹配的时候,如果设置了G,TEST匹配也相当于捕获,修改了LAST-INDEX的值
console.log(reg.exec(str));//=>['2019']

-------------------------------------------------------------------------------
let str = 'zhufeng2018';
let reg = /\d+/g;
console.log(reg.exec(str));//=>['2018'] 把REG.LAST-INDEX修改了
console.log(reg.exec('zhufeng2018peixun2019'));//=>['2019'] 虽然捕获的不是同一个字符串,但是正则是同一个,上一次正则处理的时候修改了它的LAST-INDEX,也会对下一次匹配新的字符串产生影响

------------------------------------------------------------------------------
let str = 'zhufeng2018peixun2019';
let reg = /(\d+)/g;
console.log(reg.test(str));//=>TRUE
console.log(RegExp.$1);//=>'2018' //=>把上一次匹配(TEST/EXEC)到的结果获取到,获取的是第一个小分组匹配的内容,大正则匹配的内容无法获取,它是一个全局的值,浏览器中$1只有一个,其它的正则操作也会覆盖这个值,所以这种方式没啥用
console.log(reg.test(str));//=>TRUE
console.log(RegExp.$1);//=>'2019'
console.log(reg.test(str));//=>FALSE
console.log(RegExp.$1);//=>'2019'
console.log(reg.test(str));//=>TRUE
console.log(RegExp.$1);//=>'2018'

replace:实现正则捕获的方法(本身是字符串替换)

1
2
3
4
5
6
7
8
9
10
//==============REPLACE原理
let str = 'zhufeng{val:2018}zhufeng{val:2019}',
reg = /\{val:(\d+)\}/g;
str = str.replace(reg, '@');//=>用REG正则和STR字符串进行匹配,匹配几次就替换几次,每一次都是把当前“大正则”匹配的结果用第二个传递的字符串替换掉了
console.log(str); //=>'zhufeng@zhufeng@'
--------------------------------------------------------------------
let str = 'zhufeng{val:2018}zhufeng{val:2019}',
reg = /\{val:(\d+)\}/g;
str = str.replace(reg, '$1');//=>$1不是拿这个字符串替换掉大正则匹配的内容,此处的$1代表第一个分组匹配的内容,等价于 RegExp.$1
console.log(str);//=>'zhufeng2018zhufeng2019'
  1. REG 和 STR 匹配多少次,函数就被触发执行对少次,而且传递了一些参数信息值
  2. 每一次ARG中存储的信息,和执行EXEC捕获的信息相似(内置原理:每一次正则匹配到结果,都把函数执行,然后基于EXEC把本次匹配的信息捕获到,然后把捕获的信息传递给这个函数)
  3. 每一次函数中返回的是啥,就把当前大正则匹配的内容替换成啥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 let str = "2018/4/30 17:50:23";
//1.获取时间字符串中的所有数字 (SPLIT)
let ary = str.match(/\d+/g).map(item => {
return item < 10 ? '0' + item : item;
});//=>MAP相对于FOR-EACH来讲多了返回值,函数中RETURN的是啥,就是把当前数组中迭代的这一项替换成啥
// // console.log(ary);//=>["2018", "04", "30", "17", "50", "23"]

//2. 指定最后想要的时间格式,我们基于这个数组中的内容,帮你拼接好即可
let template = '{0}年{1}月{2}日 {3}时{4}分{5}秒';
//=>{0} / 0 =>'2018' ARY[0]
//=>{1} / 1 =>'04' ARY[1]
//=>...
template = template.replace(/\{(\d)\}/g, (...arg) => {
let [, index] = arg;//=>index:每一次正则匹配小分组捕获的结果(也就是那个数字)
return ary[index];
});
// console.log(template);

时间字符串格式化

1
2
3
4
String.prototype.myFormatTime = function myFormatTime(template = '{0}年{1}月{2}日 {3}时{4}分{5}秒') {
let ary = this.match(/\d+/g).map(item => (item < 10 ? '0' + item : item));
return template.replace(/\{(\d)\}/g, (...[, index]) => ary[index] || '00');
};
-------------本文结束感谢您的阅读-------------