正则的匹配、捕获、以及正则的简单应用

1.认识正则

• (RegExp)Regular Expression:是js的一个内置类

  1. 正则,就是一个规则,可以检验某个字符串是否符合这个规则(test),也可以把字符串中符合某个规则的字符捕获到(exec 、match…)
  2. 主要用来处理字符串
let reg = /\d+/; // 0-9之间的数字出现1到多次
let str = 'd12fgh';
console.log(reg.test(str)); // true
console.log(reg.exec(str)); // ["12", index: 1, input: "d12fgh", groups: undefined]

2.正则的组成

• 正则由元字符和修饰符组成

• 正则由元字符和修饰符组成
  元字符:量词元字符、特殊元字符、普通元字符
     量词元字符:
         *: 0到多次
         +:1到多次
         ?: 0到1次
         {n}: 出现n次
         {n,}: 至少出现n次
         {n,m}: 出现n到m次
     特殊元字符:
         \ : 转义字符,可以把特殊的元字符转换为普通的元字符,也可以把普通元字符转换为特殊元字符
         . :任意字符(除了换行符意外)
         ^:以什么什么开头
         $:以什么什么结尾
         \n:换行符
         \d:0到9之间的任意数字
         \D:非0到9之间的任意数字
         \w:数字、字母、下划线
         \t:制表符
         \b:单词边界
         \s:空白符
         x|y: x和y之间的任意一个
         [a-z]:a到z之间的任意一个字符
         [a-zA-Z0-9]:a到z或者A到Z或者0到9之间的任意字符
         [^a-z]:除了a到z之外的任意一个字符
         ():分组
         (?:):只匹配,不捕获
         (?=):正向预查
         (?!):负向预查
     普通元字符:
     b
     n
     d
     ...
 修饰符:就是对正则起到修饰作用的
      i-->ignoreCase:不区分大小写
      m-->multiline:多行匹配
      g-->global:全局匹配

3.正则的简单使用

  1. 开头和结尾(^ $)

        // let reg = /18$/; // 以18结尾就可以
        // console.log(reg.test('189')) // false
        // console.log(reg.test('198')) // false
        // console.log(reg.test('218918')) // true
    
        // let reg = /^18$/; // 既要以18开头,又要以18结尾
        // console.log(reg.test('189')) // false
        // console.log(reg.test('198')) // false
        // console.log(reg.test('218918')) // false
        // console.log(reg.test('18e18')) // false
        // console.log(reg.test('18')) // true
    
        // let reg = /^\d{2}$/;
        // console.log(reg.test('e2')); // false
        // console.log(reg.test('2e')); // false
        // console.log(reg.test('2e2')); // false
        // console.log(reg.test('e2e')); // false
    
        // console.log(reg.test('22')); // true
        // console.log(reg.test('2')); // false
    
        // 如果 ^ $都不加,那只要出现正则里的字符就可以
        // 如果^ $都加,那匹配的字符必须跟正则的内容一样才可以
        let reg= /^123456$/;
        console.log(reg.test('000123456')); // true 只要结尾匹配上就可以
    
    1. 转义字符()
    // let reg = /^2.3$/;
    // . 是除了\n之外的任意字符
    // console.log(reg.test('2.3')) // true
    // console.log(reg.test('2e3')) // true
    // console.log(reg.test('2@3')) // true
    
    // 基于转义字符,把.转化成普通的元字符
    // let reg = /^2\.3$/;
    // console.log(reg.test('2.3')) // true
    // console.log(reg.test('2e3')) // false
    // console.log(reg.test('2@3')) // false
    
    // let str = '中\\国'; // 转义字符在字符串里也适用
    // console.log(str)  // '中\国'
    
    // let reg = /^\\d$/;
    // console.log(reg.test('\\d')) // true
    
    
  2. x|y : x或者y之间取一个

	//let reg = /^18|29$/;
    // console.log(reg.test('18')); // true
    // console.log(reg.test('29')); // true
    // console.log(reg.test('189')); // true
    // console.log(reg.test('129')); // true
    // console.log(reg.test('1829')); // true

---------------------------------------------------------------------------------------------
  
  直接写 x|y会存在很乱的优先级问题,一般我们写的时候都伴随着小括号进行分组,因为小括号改变处理的优先级 =>小括号:分组

  // let reg = /^(18|29)$/; 
        // console.log(reg.test('18')); // true
        // console.log(reg.test('29')); // true
        // console.log(reg.test('189')); // false
        // console.log(reg.test('129')); // false
        // console.log(reg.test('1829')); // false

//	():分组
        // 1、提高匹配的优先级
        // 2、分组引用
        // 3、分组捕获
            // 先捕获最大的内容,然后按照分组在依次进行捕获
            // let str = 'a3a';
            // let reg = /[a-z](\d)([a-z])/;
            // console.log(reg.exec(str)) // ['a3a','3',...]

4.匹配重复出现的字符(abab、abbc…)

		// let str = 'moon'; 
        // ([a-z])\1:让第一次分组的字符在出现一次
        // let reg = /^[a-z]([a-z])\1[a-z]$/;
        // console.log(reg.test('moon'));
        // console.log(reg.test('mwsn'));

        // let str = 'abab';
        // let reg = /^([a-z])([a-z])\1\2$/ // 让第一次和第二次分组的字符各自再出现一次
        // console.log(reg.test('abab'))
        // console.log(reg.test('mnmn'));
        // console.log(reg.test('aaaa'))
        // console.log(reg.test('moon'))

        // let str = 'foood';
        // let reg = /^[a-z]([a-z])\1\1[a-z]$/;  // 让第一次分组的字符在出现两次
        // console.log(reg.test('foood')) // true
        // console.log(reg.test('fonod')) // true

5.[]中不允许出现多位数

[]中不允许出现多位数

    // let reg = /^[21-68]$/; //  2 或者 1-6 或者8 之间取一个数
    // console.log(reg.test('21')); // false
    // console.log(reg.test('68')); // false
    // console.log(reg.test('2')); // true
    // console.log(reg.test('5')); // true
    // console.log(reg.test('8')); // true

    // let reg = /^[@#ws]$/; // 中括号中的字符出现一次即可

6.正则的正负向预查

/* 
        正则的正负向预查:
        (?=):正向预查
        (?!):负向预查
    */ 
   // 正向预查
        //  let reg = /zhufeng(?=peixun)/; // zhufeng后面必须跟着peixun才能匹配成功
        //  console.log(reg.test('zhufengpeixunwwwwwww')); // true

        
    // 负向预查:
        // let reg = /zhufeng(?!peixun)/;// zhufeng后面必须不跟着peixun才能匹配成功
        // console.log(reg.test('zhufengwwwwwww')) // true

        // console.log(reg.test('zhufengpeixunwww')) // false

4.正则的创建方式(字面量和构造函数创建方式)

//=>构造函数因为传递的是字符串,\需要写两个才代表斜杠
    // let reg = /\d+/g;
    // reg = new RegExp("\\d+", "g");
    // console.log(reg); // /\d+/


    //=>正则表达是中的部分内容是变量存储的值
    //1.两个斜杠中间包起来的都是元字符(如果正则中要包含某个变量的值,则不能使用字面量方式创建)
    // let type = "zhufeng";
    // reg = /^@"+type+"@$/;

    // console.log(reg.test("@zhufeng@")); //=>false
    // console.log(reg.test('@"typeeeee"@')); //=>true
    //2.这种情况只能使用构造函数方式(因为它传递的规则是字符串,只有这样才能进行字符串拼接)
    // reg = new RegExp("^@" + type + "@$");
    // console.log(reg);
    // console.log(reg.test("@zhufeng@"));//=>true

5.正则的捕获

正则的捕获:把正则匹配到的内容捕获到

let str = "asd123";
let reg = /\d{3}/;
let res = reg.exec(str);
console.log(res);// ["123", index: 3, input: "asd123", groups: undefined] 

// exec:他是正则实例的一个公有属性,用来捕获符合规则的内容
  1、返回值:是一个数组,如果捕获不到就是null
            1、第一项是最大的捕获内容
            2、数组的后几项是分组捕获的内容
            3、index是第一次捕获位置的索引
            4、input是原字符串

1.正则捕获的懒惰性
利用正则捕获时只能捕获到第一次出现符合规则的内容,如果想取消正则的懒惰性,就加修饰符g

// 正则身上有一个lastIndex属性,他记录的是正则捕获开始的位置的索引,如果正则不加g,那不管捕获多少次lastIndex始终是0,所以每一次捕获到的都是第一次负责规则的内容(这就是正则的懒惰性)
  let str = "asd123as456as789d";
  let reg = /\d{3}/;
  // console.log(reg.lastIndex); // 0
  // console.log(reg.exec(str)); // '123'
  // console.log(reg.lastIndex); // 0
  // console.log(reg.exec(str)); // '123'
  // console.log(reg.lastIndex); // 0
  // console.log(reg.exec(str)); // '123'


// 如果正则加上g,那每一次捕获之后正则的lastIndex属性就会记录下一次开始捕获的位置的索引,当下一次再次捕获的时候就会在lastIndex的位置继续捕获(这就是取消正则的懒惰性)
  reg = /\d{3}/g;
  // console.log(reg.lastIndex) // 0
  // console.log(reg.exec(str)) // '123'
  // console.log(reg.lastIndex) // 6
  // console.log(reg.exec(str)) // '456'
  // console.log(reg.lastIndex) // 11
  // console.log(reg.exec(str)) // '789'
  // console.log(reg.lastIndex) // 16
  // console.log(reg.exec(str)) // null
  // console.log(reg.lastIndex) // 0
  // console.log(reg.exec(str)) // 跟第一次一样了 '123'

2.封装一个捕获全部内容的方法(不包含分组捕获)

let str = "asd123as456as789d";
let reg = /\d{3}/g;

// 正则身上有一个global属性,如果当前正则没有修饰符g,那他的值就是false,反之就是true
function myExec(str){
    // 如果正则不加g,那正则的私有属性global的值就是false,
    // 如果global的值就是false那就把他捕获一次直接return出去就好了
    if(!this.global){
      return this.exec(str);
    };
    let ary = []; // 用来存放每一次捕获到的内容
    let res = this.exec(str) // 先捕获第一次
    while(res){
      // 每捕获一次就往ary里push一次捕获到的内容,直到捕获到null为止
      ary.push(res[0])
      // 然后在继续捕获
      res = this.exec(str) // 继续进行捕获
    }
    // 如果正则第一次就捕获不到,while就不会执行,那ary是空数组,直接给他return null就好了
    return ary.length === 0?null:ary;
};

 // RegExp.prototype.myExec = myExec;
 // console.log(reg.myExec(str)); // ['123','456','789']

3.字符串的match方法
String.prototype.match()
match是字符串上的一个方法,用来捕获负责符合规则的内容

let str = "asd123as456as789d";
let reg = /\d{3}/g;
console.log(str.match(reg)); // ['123','456','789'] 和咱们刚才封装的方法实现的功能是一样的
// ---------------------------------------------------------------------------------------

// match的其他特点:
 let str = "{0}年{1}月{2}日";
 let reg = /\{(\d+)\}/;

//=>如果正则不设置g只会捕获一次,exec和match获取的结果一致
 console.log(reg.exec(str)); // ["{0}", "0", index: 0, input: "{0}年{1}月{2}日", groups: undefined]
 console.log(str.match(reg)); // ["{0}", "0", index: 0, input: "{0}年{1}月{2}日", groups: undefined]

//=>如果正则加上g,在多次捕获的情况下match只能把大正则匹配的内容获取到,小分组匹配的信息无法获取
 reg = /\{(\d+)\}/;
console.log(str.match(reg)); // ["{0}", "{1}", "{2}"]

4.字符串的matchAll方法
String.prototype.matchAll()
match是字符串上的一个方法,他的返回值是一个迭代器,迭代器里的每一项是每一次捕获到的所有内容(大捕获和分组捕获) 【迭代器可以用for of遍历】

 let str = "{0}年{1}月{2}日";
    let reg = /\{(\d+)\}/g;
    console.log(str.matchAll(reg)); // RegExpStringIterator {} 迭代器
    for (var ss of str.matchAll(reg)) {
      console.log(ss);
      // ["{0}", "0", index: 0, input: "{0}年{1}月{2}日", groups: undefined]
      // ["{1}", "1", index: 4, input: "{0}年{1}月{2}日", groups: undefined]
      // ["{2}", "2", index: 8, input: "{0}年{1}月{2}日", groups: undefined]
    }
// 去遍历当前的迭代器可以得到每一次捕获的所有内容

5.正则的贪婪性
正则捕获的贪婪性:默认情况下,正则捕获的时候,是按照当前正则所匹配的最长结果来获取的
在量词元字符后面设置?来取消正则的贪婪性

// 正则的贪婪性
let str = '2019';
let reg = /\d+/g;
console.log(str.match(reg)); // ['2019']

//=>在量词元字符后面设置?来取消捕获时候的贪婪性(按照正则匹配的最短结果来获取)
reg = /\d+?/g;
console.log(str.match(reg)); // ["2", "0", "1", "9"]

猜你喜欢

转载自blog.csdn.net/hanruo7532/article/details/112306700