正则表达式--语法篇

思考题一:字符串拼接规则

字符串拼接规则 外双内单 外单内双

var str = "我是一名"牛逼"的程序员";   // 为什么报语法错误?
document.write(str);
根本原因:javascript先解析的是正常的语法

解析过程 =》  "我是一名" "的程序员" 这是字符串的语法; 然后 中间是变量

把语法分析完毕之后,才会做文本输出。当做文本输出的时候,发现变量与字符串中间没有加号,这时候才会报语法错误

改错一:使用转义字符,改变一下

var str = "我是一名\"牛逼\"的程序员";
document.write(str); // 结果:"我是一名"牛逼"的程序员"

var str = "我是一名\\牛逼\\的程序员"; 
document.write(str); // 结果:"我是一名\牛逼\的程序员"

改错二:

 var str = "我是一名\n牛逼\n的程序员";
 document.write(str); // 我是一名 牛逼 的程序员
问题:页面为什么会识别为一个空格? 

因为: \n \r \t 这是给编辑系统用的,不是给html用的
html实体:用于处理html当中特殊的字符,如: > &gt;  < &lt;  为什么没有  \n \r \t 呢??

因为  \n \r \t 都是编辑的时候用的,咱们的编辑器如vscode,每次换行,
在编辑器系统软件内部其实都有一个换行 \n ,这是系统级别的

而html页面是纯文本的,编译以后文本显示出来的,所以html不可能识别  \n \r \t

有空格的原因:是因为 \n 占用了字符

思考二:不允许字符串多行

var str = '<h1>我是小白</h1>
		   <h2>从事前端编程</h2>
           <h3>目标高级前端</h3>'; // 这样写系统会报错

/*
  根本原因:javascript 默认不允许字符串多行 【牢记】
*/

改错一:字符串拼接 【有点傻不推荐】

 var str = '<h1>我是小白</h1>'+
           '<h2>从事前端编程</h2>'+
           '<h3>目标高级前端</h3>';
  var wrap = document.getElementsByTagName('div')[0];
  wrap.innerHTML = str;

改错二:使用转义符号,把回车和换行进行转义为空格 ( 把标签左右的空白转义为空格 )

控制台打印结果:

<h1>我是小白</h1>              <h2> 从事前端编程</h2>              <h3> 目标高级前端</>
var str = '<h1>我是小白</h1>\
		   <h2>从事前端编程</h2>\
           <h3>目标高级前端</h3>';
  var wrap = document.getElementsByTagName('div')[0];
  wrap.innerHTML = str;

改错三:使用模板拼接 【推荐】

<body>
    
  <div id="div" style="background:green;"></div>

  <script type="text/template" id="div2">
    <div>数据:{{data}}</div>
    <div>年龄:{{age}}</div>
    <div>姓名:{{name}}</div>
   </script>

  <script type="text/javascript">
    var div = document.querySelector('#div');
    var div2 = document.getElementById('div2');

    var data = { data: "123", name: "csdn", age: "xxoo" };
    div.innerHTML = div2.innerHTML.replace(/\{\{([\s\S]+?)\}\}/g, ($0, $1) => { 
        return data[$1] || ''; 
    }); 
  </script>
</body>

转义符号 和 转义字符的区别

  • 转义符号: \

  • 转义字符:\字符

  • 特殊的转义字符:\n\r\t,它们有特定的功能

    \n :表示换行 \t:表示tab键,代表4个空格

第 1 章:正则表达式

1.1 含义

含义:正则表达式是一些用来匹配和处理文本的字符串。它有两种基本用途:搜索和替换

给定一个正则表达式,它要么匹配一些文本(进行一次搜索),要么匹配并替换一些文本(进行一次替换)

1.2 创建方式

方式一:构造函数模式

实例化一个正则对象 形如:var obj = new Object();有两个参数:new RegExp()

参数1:正则表达式

参数2:一些修饰符,如: i (忽略大小写) g(全局) m(多行匹配)

  • 只能处理字符串

  • 它是一个规则:可以验证字符串是否符合某个规则(test),

    也可以把字符串中符合规则的内容捕获到(exec / match…)

//=> 在字符串中,两个斜杠才代表斜杠的意思!!!
let reg2 = new RegExp("\\d+");
//=>例如:\n 表示换行 ;\\n 代表 \n本身
 var reg = new RegExp('test'),
      str = 'This is a test';
    console.log(reg.test(str)); // true

 var reg = new RegExp('Test'),
      str = 'This is a test';
    console.log(reg.test(str)); // false

 var reg = new RegExp('est'),
      str = 'This is a test';
    console.log(reg.test(str)); // true


/*
  表达的含义:以正则表达式为规则,检验字符串str中是否 包含 指定的字符串片段
  注意:要求是连续的字符串片段 对于大小写敏感 
*/

修改一:添加修饰符 i ( ingore case ),忽略大小写

  var reg = new RegExp('Test', 'i'),
      str = 'This is a test';
    console.log(reg.test(str)); // true

//=>拓展:match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配

 var reg1 = new RegExp('Test', 'i'), // 忽略大小写
      str1 = 'This is a test. Test is important';
    console.log(str1.match(reg1));
    // ["test", index: 10, input: "This is a test. Test is important", groups: undefined]

 var reg2 = new RegExp('Test', 'ig'), // 忽略大小写且全局匹配
      str2 = 'This is a test. Test is important';
    console.log(str2.match(reg2)); // ["test", "Test"]

 var reg = new RegExp('^Test', 'igm'),// 忽略大小写且全局匹配且多行匹配  匹配以Test开头的
      str = 'This is a test. \nTest is important';
    console.log(str.match(reg)); // ["Test"]

方式二:字面量创建方式

两个斜杆之间包起来的,都是用来描述正则规则的元字符

 var reg =/test/,
      str = 'This is a test';
    console.log(reg.test(str)); // true

var reg =/Test/,
      str = 'This is a test';
    console.log(reg.test(str)); // false

 var reg =/est/,
      str = 'This is a test';
    console.log(reg.test(str)); // true

  var reg =/Test/i,
      str = 'This is a test';
    console.log(reg.test(str)); // true

//=>拓展:match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配

  var reg1 =/Test/i, // 忽略大小写
      str1 = 'This is a test. Test is important';
    console.log(str1.match(reg1));
    // ["test", index: 10, input: "This is a test. Test is important", groups: undefined]

  var reg2 =/Test/ig, // 忽略大小写且全局匹配
      str2 = 'This is a test. Test is important';
    console.log(str2.match(reg2)); // ["test", "Test"]

  var reg3 =/^Test/igm,// 忽略大小写且全局匹配且多行匹配  匹配以Test开头的
      str3 = 'This is a test. \nTest is important';
    console.log(str3.match(reg3)); // ["Test"]

两种创建方式的区别

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

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

//=>2.这种情况只能使用构造函数方式(因为它传递的规则是字符串,只有这样才能进行字符串拼接)
let type1 = "lisi";
reg1 = new RegExp("^@"+type1+"@$");
console.log(reg1.test("@lisi@"));//=>true
 /*
   思考正则匹配的规则:【匹配成功的不会再倒回去匹配】 而是连续的进行匹配
   例如: 123 匹配成功 就不会 再去匹配 234 而是接着找 4ds 没匹配上 接着往下找...
   找到 p34 没匹配成功 但是 345匹配成功了 【前面没匹配成功,才会倒回去接着匹配】
 */
var str = '1234dsf3rp345df35q',
      reg = /[1234567890][1234567890][1234567890]/g;
    console.log(str.match(reg)); //  ["123", "345"]

 var str = 'wxyz',
      reg = /[wx][xy][z]/g;
    console.log(str.match(reg)); // ["xyz"]

 var str = 'we24DsaD34',
      reg = /[0-9][A-Z][a-z]/g;
    console.log(str.match(reg)); // ["4Ds"]

 /*
      找4位字符串
      第一位:不是0 [^0]
      第二位:0-9之间的数字 或者 A-Z 或者 a-z
      第三位:A-Z
      第四位:a-z
    */
    var str = 'wAeA24DsaD34',
      reg = /[^0][0-9A-z][A-Z][a-z]/g;  
    console.log(str.match(reg)); // ["24Ds"]

 	/*
       (x | y)  x或者y中的一个字符  加小括号优先级较高
    */
    var str = '123zAeA24Dsa234w',
      reg = /(123|234)[xyz]/g;
    console.log(str.match(reg)); // ["123z"]

     /*
     	匹配单词的边界:\b
     */
      var str = 'Thiese is a Thise text',
        reg = /\bThi\B/g;
      console.log(str.match(reg)); // ["Thi", "Thi"]

第 2 章:正则表达式由两部分组成

2.1 元字符

2.1.1 量词元字符:设置出现的次数

元字符含义
*零到多次
+一到多次
?零次或者一次
{n}出现n次
{n,}出现n到多次
{n,m}出现n到m次

举例说明:

/*
       正则匹配的原则:
       匹配成功不回头、
       贪婪模式:能匹配多就不会匹配少,例如:abcdefg匹配成功,就不会再匹配 a、abc等
    */
    var reg = /\w+/g;
    str = 'abcdefg';
    console.log(str.match(reg)); // ["abcdefg"]

/*
       正则匹配的原则:
       字符串从左到右,依次先匹配多,再匹配少,如果一旦匹配上就不回头匹配 =》 匹配成功不回头
       贪婪匹配原则:能匹配多就不会匹配少

       正则要求:* 0到多次
        匹配过程:先匹配多,找到 abcdefg 当光标移动到g后面 再匹配空  ["abcdefg", ""]
       【因为 abcdefg 匹配成功,所有不会回头匹配前面字母前后的空】,只能匹配g字母后面的空
    */
    var reg = /\w*/g;
    str = 'abcdefg';
    console.log(str.match(reg)); // ["abcdefg", ""]

 /*
       正则匹配的原则:
       匹配成功不回头、
       贪婪模式:能匹配多就不会匹配少

       正则要求:* 0到多次
        匹配过程:先匹配 0-9之间的数字,找不到 然后在匹配空 
        光标走到哪里就匹配一个空 => 三个空 => a字母前后的空 和 b字母后的空
    */
    var reg = /\d*/g;
    str = 'ab';
    console.log(str.match(reg)); //  ["", "", ""]

/*
       正则匹配的原则:
       匹配成功不回头、
       贪婪模式:能匹配多就不会匹配少

       正则要求:* 0到多次
        匹配过程:先匹配 0-9之间的数字,找不到 然后在匹配空 
        匹配三个空 =>a字母前后的空和b字母后的空
    */
    var reg = /\w?/g;
    str = 'ab';
    console.log(str.match(reg)); //  ["a", "b", ""]

  /*
       正则匹配的原则:
       匹配成功不回头、
       贪婪模式:能匹配多就不会匹配少

       正则要求:
       {n,m} 出现n到m次
       {1,}  出现1到多次  === +
       {0,}  出现0到多次  === *
       {0,1} 出现0或者1次 === ?
    */
    var reg = /\w{1, 2}/g;
    str = 'abcdefg';
    console.log(str.match(reg)); //  ["ab", "cd", "ef", "g"]

 	/*
      ^n  匹配任何以n开头的字符串
    */

    var reg = /^ab/g,
      str = 'abcdabcd';
    console.log(str.match(reg)); ["ab"]

2.1.2 特殊元字符:

单个或者组合在一起代表特殊的含义

元字符含义
\转义字符(普通->特殊->普通)
.可以匹配除了回车和换行的所有字符
^ 和 $^ 以哪一个元字符作为开始,$ 以哪一个元字符作为结束
\d=== [0-9] 0~9之间的一个数字
\D=== [^\d] 非0~9之间的一个数字 【大写和小写的意思是相反的】
\w=== [0-9A-z_] 数字、字母、下划线中的任意一个字符
\W=== [^\w] 非数字、字母、下划线中的任意一个字符
\s=== [\r\n\t] 一个空白字符,包含:回车\r、空格、换行\n、制表符\t、\v垂直换行符、\f换页符 等
\S=== [^\s]
\n、\t、换行符\n、一个制表符\t(一个Tab键:四个空格)
\b、\B匹配一个单词的边界\b;非单词边界\B
x|yx或者y中的一个字符
[xyz]x或者y或者z中的一个字符
[^xy]除了x/y以外的任意字符
[a-z]指定a-z这个范围中的任意字符 [0-9a-zA-Z] === \W;
[^a-z]上一个的取反“非”
//=> 2.特殊元字符:单个或者组合在一起代表特殊的含义
 ****************************************************
 ()		正则中的分组符合
 (?:)	只匹配不捕获
 (?=)	只匹配不捕获、正向预查(设置一个正向条件,必须条件符合啥)
 (?!)	只匹配不捕获、负向预查(设置一个负向条件,必须条件不符合啥)
普通元字符:

代表本身含义的

 //=> 3.普通元字符:代表本身含义的
 /zhangfeng/  此正则匹配的就是 "zhufeng"
 

2.1.3 元字符详细解析

^ $
//=> ^/$ 两个都不加:字符串中包含符合规则的内容即可
let reg1 = /\d+/;

//=> ^/$ 两个都加:字符串只能是和规则一致的内容
let reg1 = /^\d+$/;

//=> 举个例子:验证手机号码(11位,第一个数字是1即可)
let reg = /^1\d{10}$/;
\
//=> .不是小数点,是除\n外的任意字符
 let reg = /^2.3$/;
 console.log(reg.test('2.3'));//=>true
 console.log(reg.test('2@3'));//=>true
 console.log(reg.test('23'));//=>false (因为2和3之间没有字符,结果为:false)

//=> 基于转义字符,让其只能代表小数点
 let reg = /^2\.3$/;
 console.log(reg.test('2.3'));//=>true
 console.log(reg.test('2@3'));//=>false

 //=> 在字符串中,\d也有特殊含义(0~9之间的任意数字),如果表示本身含义需要转义,如:\\d
 let str = '\\d';
 reg = /^\d$/;
 console.log(reg.test(str));//=>false
 reg = /^\\d$/;
 console.log(reg.test(str));//=>true

x|y
let reg = /^18|29$/;
//=> 下面的打印结果,全是true
console.log(reg.test("18"))
console.log(reg.test("29"))
console.log(reg.test("129"))
console.log(reg.test("189"))
console.log(reg.test("1829"))
console.log(reg.test("829"))
console.log(reg.test("182"))

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

let reg = /^(18|29)$/;
console.log(reg.test("18"));//=> true
console.log(reg.test("29"));//=> true
console.log(reg.test("129"));//=> false
console.log(reg.test("189"));//=> false
console.log(reg.test("1829"));//=> false
console.log(reg.test("829"));//=> false
console.log(reg.test("182"));//=> false
//=> 只能是18或者29中的一个了
[]
//=> 1.中括号中出现的字符一般都代表本身的含义
//=> [@+]  表示:@或者+中的一个字符
let reg = /^[@+]+$/;
console.log(reg.test("@"));//=>true
console.log(reg.test("+"));//=>true
console.log(reg.test("@@"));//=>true
console.log(reg.test("@+"));//=>true

//=>例外情况:
//=>[\d]   中括号里面的\d 表示:0~9之间的任意数字
let reg = /^[\d]$/;
console.log(reg.test("d"));//=>false
console.log(reg.test("\\"));//=>false
console.log(reg.test("9"));//=>true

//=>中括号中不存在多位数
reg = /^[18]$/;
console.log(reg.test("1"));//=>true
console.log(reg.test("8"));//=>true
console.log(reg.test("18"));//=>false

//=>例如:
let reg = /^[10-29]$/; //=>1或者0-2或者9
console.log(reg.test("1"));//=>true
console.log(reg.test("9"));//=>true
console.log(reg.test("0"));//=>true
console.log(reg.test("2"));//=>true
console.log(reg.test("0-2"));//=>false
console.log(reg.test("10"));//=>false

let reg = /^[(10-29)]$/; //=>( 或者 1 或者 0-2 或者 9 或者 )
console.log(reg.test("("));//=>true
console.log(reg.test(")"));//=>true

2.2 修饰符

 //=> 正则表达式常用的修饰符:img
 i	=>ignoreCase	忽略单词大小写匹配
 m	=>multiline		可以进行多行匹配
 g	=>global		全局匹配

第 3 章:正则的捕获

3.1 实现正则捕获的方法

方法函数
正则RegExp.prototype上的方法exec()、test()
字符串String.prototype上支持正则表达式 处理的方法replace()、match()、splite()
  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));//=>false
console.log(RegExp.$1);//=> 2 存储的是上一次捕获的结果

//=>RegExp.$1 ~ RegExp.$9:获取当前本次正则匹配后,第一个到第九个分组的信息
  1. replace字符串中实现替换的方法(一般都是伴随正则一起使用的)
    • 把“zhufeng”替换成“珠峰”
 //=>1.不用正则,执行一次只能替换一个
 let str = "zhufeng@2019|zhufeng@2020"
 str = str.replace("zhufeng","珠峰").replace("zhufeng","珠峰")
 console.log(str);//=>珠峰@2019|珠峰@2020

 //=>2.使用正则会简单一点
 let str = "zhufeng@2019|zhufeng@2020"
 str = str.replace(/zhufeng/g,"珠峰");
 console.log(str);//=>珠峰@2019|珠峰@2020
  • 把"zhufeng"替换为"zhufengpeixun"
 //=>基于正则g可以实现
 let str = "zhufeng@2019|zhufeng@2020"
 str = str.replace(/zhufeng/g,"zhufengpeixun");
 console.log(str);//=>zhufengpeixun@2019|zhufengpeixun@2020

案例:把时间字符串进行处理

 //=>方法1:
 let time = "2019-08-13";
 let reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/g;
 time = time.replace(reg,"$1年$2月$3日");
 console.log(time)//=>2019年08月13日

 //=>方法2:[str].replace([reg],[function])
 // 1.首先拿reg 和 time 进行匹配捕获,能匹配到几次就会把传递的函数执行几次
 // (而且是匹配一次就执行一次)
 // 2.不仅把方法执行,而且replace还给方法传递了实参信息
 // (和exec捕获的内容一致的信息:大正则匹配的内容,小分组匹配的信息...)
 // 3.在函数中我们返回的是啥,就把当前大正则匹配的内容替换成啥

let time = "2019-08-13";
let reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/g;
time = time.replace(reg,(big,$1,$2,$3)=>{
    //=>这里的$1 ~ $3 是我们自己设置的变量
    console.log(big,$1,$2,$3)
})

//=> 一般我们这样书写:
let time = "2019-08-13";
let reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/g;
time = time.replace(reg, (...arg) => {
    let [, $1, $2, $3] = arg
    $2.length < 2 ? $2 = "0" + $2 : null;
    $3.length < 2 ? $3 = "0" + $3 : null;
    return $1 + "年" + $2 + "月" + $3 + "日"
})
console.log(time); //=>2019年08月13日
 

案例:单词首字符大写

let str = "good good study, day day up!";
let reg = /\b([a-zA-Z])[a-zA-Z]*\b/g;
//=> 函数被执行了六次,每一次都把正则匹配信息传递给函数
//=> 每一次arg: ["good","g"] ["good","g"] ["study","s"] ...
str = str.replace(reg,(...arg)=>{
let [content,$1] = arg;
// 首字符大写
$1 = $1.toUpperCase();
// 出第一个字母以外,其余都拿到 例如:good 除了g不要,剩余的 ood 都要拿到
content = content.substring(1);
return $1 + content // G 拼接 ood 得到 Good
})
console.log(str); //=>Good Good Study, Day Day Up!
let str = "zhufnengjjdaf2001jkjk2004";
let reg = /^\d+s/;
//=>实现正则捕获的前提是:当前正则要和字符串匹配,如果不匹配捕获的结果是null
console.log(reg.test(str)); //=>false
console.log(reg.exec(str)); //=>null

3.2 正则捕获的贪婪性

//=>正则捕获的贪婪性:默认情况下,正则捕获的时候,是按照当前正则所匹配的最长结果来获取的
let str = "接口2019@2020培新"
let reg = /\d+/g;
console.log(str.match(reg));//=>["2019", "2020"]

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

问号在正则中的5大作用

  • 问号左边是非量词元字符:本身代表量词元字符,出现零到一次
  • 问号左边是量词元字符:取消捕获时候的贪婪性
  • (?😃 只匹配不捕获
  • (?=) 正向预查
  • (?!) 负向预查

3.3 正则捕获的懒惰性

/*
 基于exec实现正则的捕获:
	1.捕获到的结果是null 或者 一个数组
	  第一项:本次捕获的内容
	  其余项:对应小分组本次单独捕获的内容
	  index:当前捕获内容在字符串中的起始索引
	  input:原始字符串
	2.每执行一次exec,只能捕获到一个符合正则规则的,但是默认情况下,我们执行多次(无数次),获取的结果永远都是第一个匹配到的内容,其余的捕获不到。 //=>"正则捕获的懒惰性":默认只捕获第一个

*/

let str = "zhufnengjjdaf2001jkjk2004";
let reg = /\d+/;
console.log(reg.exec(str)); 
//=>结果:["2001", index: 13, input: "zhufnengjjdaf2001jkjk2004", groups: undefined]
  • 正则捕获的懒惰性的原因:
let str = "zhufnengjjdaf2001jkjk2004";
let reg = /\d+/;
console.log(reg.lastIndex);//=>0 下面匹配捕获是从STR索引零的位置开始找
console.log(reg.exec(str)); 
console.log(reg.lastIndex);//=>0 第一次匹配捕获完成,lastIndex没有改变,所以下一次exec依然是从字符串最开始找,找到的永远是第一个匹配到的

/*
	reg.lastIndex : 当前正则下一次匹配的起始索引位置
	懒惰性捕获的原因:默认情况下lastIndex的值不会被修改,每一次都是从字符串开始位置查找,
	所以找到的永远只是第一个
*/
  • 懒惰性捕获的解决方法: 全局匹配修饰符g
//=> 设置全局匹配修饰符g后,第一次匹配完;lastIndex会自己修改

let str = "zhufnen2019gjjdaf2001jkjk2004";
let reg = /\d+/g;
console.log(reg.exec(str)); //=>["2019"...]
console.log(reg.lastIndex); //=>11
console.log(reg.exec(str)); //=>["2001"...]
console.log(reg.lastIndex); //=>21
console.log(reg.exec(str)); //=>["2004"...]
console.log(reg.lastIndex); //=>29
console.log(reg.exec(str)); //=>null 当全部捕获后,再次捕获的结果是null,但是lastIndex又回归了初始值零,再次捕获又从第一个开始了...

console.log(reg.lastIndex); //=>0
console.log(reg.exec(str)); //=>["2019"...]
console.log(reg.lastIndex); //=>11
							//=>...依次循环
  • 验证一下:只有正则和字符串匹配,我们再捕获 ( 不能采用下面的方法 )
let str = "zhufnen2019gjjdaf2001jkjk2004";
let reg = /\d+/g;
if(reg.test(str)) {
   console.log(reg.lastIndex); //=>11 基于TEST匹配验证后,lastIndex已经被修改为第一次匹配后的结果,所以下一次捕获不再从头开始了
   console.log(reg.exec(str)); //=>["2001"...]
}
  • 字符串中的match方法原理:
 ~function () {
     function execAll(str = "") {
         //=>str: 要匹配的字符串
         //=>this: RegExp的实例(当前操作的正则)
         //=>进来后的第一件事,是验证当前正则是否设置了g,不设置则不能再进行循环捕获了,否则会导致死循环
         if (!this.global) return this.exec(str);
         //=>ary 存储最后所有捕获的信息 res 存储每一次捕获的内容
         let ary = []
         res = this.exec(str)
         while (res) {
             //=>把每一次捕获的内容res[0]存放到数组中
             ary.push(res[0]);
             //=>只要捕获的内容不为null,则继续捕获下去
             res = this.exec(str)
         }
         return ary
     }
     RegExp.prototype.execAll = execAll
 }();
let str = "zhufnen2019gjjdaf2001jkjk2004";
let reg = /\d+/g;
console.log(reg.execAll(str)) //=> ["2019", "2001", "2004"]
//=>字符串中的match方法,可以在执行一次的情况下,捕获到所有匹配的数据(前提是:正则也得设置g才可以)
console.log(str.match(reg)); //=> ["2019", "2001", "2004"]
  • match方法的局限性:
//=>多次匹配的情况下,match只能把大正则匹配的内容获取到,小分组匹配的信息无法获取
let str = "{0}年{1}月{2}日";
let reg = /\{(\d+)\}/g;
console.log(str.match(reg));
//=>结果:["{0}", "{1}", "{2}"]

3.4 正则的分组捕获

1.//=>身份证号码
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|x)$/g
let str = "130828199012040112"
console.log(reg.exec(str));
//=>结果:["1	30828199012040112", "130828", "1990", "12", "04", "1", "2", index: 0, input: "130828199012040112", groups: undefined]
//=>第一项:大正则匹配的结果
//=>其余项:每一个小分组单独匹配捕获的结果
//=>如果设置了分组(改变优先级),但是捕获的时候不需要单独捕获,可以基于?:来处理
console.log(str.match(reg));
//=>结果:["130828199012040112"]
//=>既要捕获到数字{数字},也想单独的把数字也获取到,
//=>例如:第一次找到{0};还需要单独获取 0
let str = "{0}年{1}月{2}日";

//=>不设置g只匹配一次,exec和match获取的结果一致(既有大正则匹配的信息,也有小分组匹配的信息)
let str = "{0}年{1}月{2}日";
let reg = /\{(\d+)\}/;
console.log(reg.exec(str));
console.log(str.match(reg));
//=>结果:["{0}", "0", index: 0, input: "{0}年{1}月{2}日", groups: undefined]

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

//=>解决方法:
let str = "{0}年{1}月{2}日";
let reg = /\{(\d+)\}/g;
let aryBig = []
arySmall = []
res = reg.exec(str)
while (res) {
    let [big, small] = res;
    aryBig.push(big);
    arySmall.push(small);
    res = reg.exec(str)
}
console.log(aryBig,arySmall)
//=>结果:["{0}", "{1}", "{2}"]  ["0", "1", "2"]

3.5 正则的分组引用

//=>分组的第三个作用: “分组引用”
 let str = "book"
//=> 分组引用就是通过“\数字”让其代表和对应分组出现一模一样的内容
 let reg = /^[a-zA-Z]([a-zA-Z])\1[a-zA-Z]$/
console.log(reg.test(str)) //=>true
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落花流雨

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值