四、正则捕获(二)

本篇是对上一篇的进一步补充。会讲到以及。

一、正则的分组匹配

    首先还是以前面讲解过的身份证验证的那个案例为基准,进行讲解。

let str = '622426189812012541'
let reg = /^(\d{6})(\d{8})\d{2}(\d)(\d|X)$/;
// console.log(reg.test(str));
console.log(reg.exec(str)); // => ["622426189812012541", "622426", "18981201", "4", "1", index: 0, input: "622426189812012541"]
// => 从返回的结果来看,第一个为匹配的大正则的内容,后面依次是小分组的内容。
注意:

\color{red}{ 1、要进行分组匹配的前提是一定要通过test检测,也就是被检测的字符串和制定的正则表达式要匹配成功,如果不成功,分组捕获的结果永远是null}

二、使用(?:)实现职匹配不捕获的操作

    在上面的例子中我们为了解决(\d|X)带来的优先级问题,我们在使用小括号,但是小括号会存在分组的情况,也就是这个这个小分组匹配的结果我们并需要,这个时候我们可以使用(?:)来实现这样的的功能。

let str = '622426189812012541'
let reg = /^(\d{6})(\d{8})\d{2}(\d)(?:\d|X)$/;
// console.log(reg.test(str));
console.log(reg.exec(str));  // => ["622426189812012541", "622426", "18981201", "4", index: 0, input: "622426189812012541"]
// => 从结果来看 设置了(?:)的分组并没有匹配到。

三、正则捕获的贪婪性

在默认的情况下,正则捕获的时候,是按照当前正则所匹配的最长的结果俩获取的。

let str = 'antiai2019antiai2018'
let reg = /\d+/g;
console.log(str.match(reg)); // => ["2019", "2018"]
reg = /\d+?/g;
console.log(str.match(reg)); // => ["2", "0", "1", "9", "2", "0", "1", "8"]
// 关于上面正则的贪婪性 我们也可以通过下面的方式来解决问题
let reg = /\d/g;
let str = ‘antiai2019antiai2018’;
console.log(str.match(reg))   // =>  ["2", "0", "1", "9", "1", "0", "2", "3"]

?在正则表达式中作用

四、分组引用

let str = "book"  // => "good"  "look"  "moon"  "foot"
let reg = /^[a-zA-Z]([a-zA-Z])\1[a-zA-Z]$/

// 通过 \数字让其代表和对应的分组出现一模一样的内容
console.log(reg.test('book'));   // => true
console.log(reg.test('deep'));  // => true
console.log(reg.test('dome')); // => false
let str = "book"  // => "good"  "look"  "moon"  "foot"
let reg = /^[a-zA-Z]([a-zA-Z])(m)\2[a-zA-Z]$/
        
// 通过 \数字让其代表和对应的分组出现一模一样的内容
console.log(reg.test('boeok'));  // =>false
console.log(reg.test('deeep')); // => false
console.log(reg.test('domme')); // => true

     仔细对比这两对代码可以发现(\数字)中的【数字】代表的是我们的制定正则中的分组的位置数。(默认从1开始计算)。

四、其他的捕获方式

test也可以进行捕获

let str = '{0}年{1}月{2}日'
let reg = /\{(\d+)\}/g;
        
console.log(reg.test(str));   // => true
console.log(RegExp.$1);   // => 0
        
console.log(reg.test(str));  // => true
console.log(RegExp.$1);  // => 1
        
console.log(reg.test(str));  // => true
console.log(RegExp.$1); // => 2
        
console.log(reg.test(str));  // => true
console.log(RegExp.$1);  // => 2     储存的是上次匹配的结果
// RegExp.$1~RegExp.$9:  获取当前匹配正则后一个到第九个的分许信息

let str = 'abc#12#'
let reg = /([a-z]+).(\d+)./g;
        
console.log(reg.test(str));  // => true
console.log(RegExp.$1);   // => abc
console.log(RegExp.$2);   // => 12
        
console.log(reg.test(str));  // => false
console.log(RegExp.$1);   // => abc
console.log(RegExp.$2);   // => 12
        
console.log(reg.test(str));   // => true
console.log(RegExp.$1);    // => abc
console.log(RegExp.$2);   // => 12
        
console.log(reg.test(str)); // => false
console.log(RegExp.$1);   // => abc
console.log(RegExp.$2);  // => 12

比较上面代码们可以感受一下 RegExp.9这种方式的强大,不过,在匹配完成后,再次进行结果匹配,将会从头再来。

这里我们来看一下非常有意思的例子

// => 既要捕获到数字,越要单独吧数字获取到,例如第一次找到是{0},还需要单独获取0。
let str = '{0}年{1}月{2}日';
// => 不设置g只能匹配一次,exec和match获取的结果一致,既有大正则匹配的信息,也有小分组匹配的信息。
let reg = /\{(\d+)\}/g;
console.log(reg.exec(str));     // =>  ["{0}", "0", index: 0, input: "{0}年{1}月{2}日", groups: undefined]
console.log(str.match(reg));   // =>["{0}", "{1}", "{2}"]
// 在使用g的情况下,macth方法会获取大正则匹配的信息,而不会获取到小分组匹配的信息。
// 可以借助exec的这种特性来递归实现我们的需求

let reg = /\{(\d+)\}/g;
let aryBig = [],
     arySmall = [],
     res = reg.exec(str);
while(res){
   let [big,small] = res;
   aryBig.push(big);
  arySmall.push(small);
 reg.exec(str);
} 
console.log(aryBig,arySmall);

你可能感兴趣的:(四、正则捕获(二))