正则表达式

RegExp 正则表达式(regular Expression)又名 规则表达式,正则表达式是一个复杂数据类型

作用:1 专门用来验证字符串是否符合规则

2 从字符串里面获取一部分符合规则的内容

语法:

  • 使用一些特殊符号,来组合成一个表达式

  • 使用这个表达式去验证字符串,或者从字符串里面获取一些内容

创建一个正则表达式

1 字面量形式创建

var reg=/abcd/

const reg=/abcd/;
console.log(reg)
console.log(typeof reg);   object

2 内置构造函数创建

var res=new RegExp(‘abcd’);

const reg2=new RegExp('abcd');
console.log(reg2)
console.log(typeof reg2)

意义:字符串里包含一段 abcd 字母就可以了

检测:aaaabbbbcccddd 不合格

123abcddhhdh 合格

正则表达式的两个方法

  • 匹配:验证字符串是不是符合正则规则

    语法:正则.test(你要检测的字符串)

    返回值:一个布尔值 ,true 或 false

    const reg=/abcd/;
    console.log(reg)
    console.log(typeof reg)   
    console.log(reg.test('abcdefg'));   true
  • 捕获:从字符串里面捕获符合正则规则的那一部分片段

    语法:正则.exec(你要捕获的字符串)

    console.log('11111.....',reg.exec('abcdefg66'));
    //['abcd', index: 0, input: 'abcdefg66', groups: undefined]

    返回值:

    • 1 字符串里面没有符合规则的片段。 –》 null

    • 2 字符串里有符合规则的片段

      • 2.1 基础捕获

      返回值是一个数组,索引0 是捕获来的片段,不管有多少个片段,都只捕获第一个片 段,不管捕 获多少次,都是第一个片段

      index:0 是从哪一个索引开始拿到的

      input:’abcdefg66′ 你输入的原字符串是哪个,我从哪个字符串里拿出来的东西

      • 2.2 (最后再总结)当基础表达式有小括号()的时候,返回值是一个数组,从索引[1]开始依次是每一个小括号单独捕获

      • 2.3 (最后再总结)当正则有全局表示符g的时候,第二次捕获会从第一次捕获的结束位继续向后查找,直到找不到了为止返回null,下面一次捕获,依旧会从索引[0]位置开始查找

正则表达式的元字符 – 基础元字符

元字符:组成正则的基本符号,以符号的形式代替文本内容,把所有的文本内容归结成一些符号来代替

  • \s (小s)表示字符串里需要有一个空格 字符

  const  reg=/\s/; 等价于 / /
  console.log(reg.test('abc tt')); //true
  • \S (大S)表示字符串里需要一个字符,还需要一个空格,就为true, 如果只有空格是false

    const  reg=/\S/
    console.log(reg.test(' ')); //fasle
        console.log(reg.test(' 1')) ; //true
  • \t 表示你的字符串里要有一个 制表符 字符 tab缩进,注意要调整vscode的缩进方式,默认是空格,空格和tab缩进看着一样,但实际是不同的

    const  reg=/\t/
    console.log(reg.test('  ')); // false 此处是两个空格
    console.log(reg.test('  ')); //true 此处是一个制表符 (tab缩进)
  • \d 表示字符串里包含有一个数字(0到9)字符 digit (零到九中的任一)数字

        const  reg=/\d/
        console.log(reg.test('1111')); //true
            console.log(reg.test('dhasf')); //false
  • \D 表示字符串里要有一个非数字

    const  reg=/\D/
    console.log(reg.test('1111')); //false
		console.log(reg.test('dhasf')); //true
  • \w (小w)表示有一个 数字 字母 下划线

  const  reg=/\w/
  console.log(reg.test('1111'));   //true
	console.log(reg.test('dhasf')) ;   //true
  console.log(reg.test('-……&*(……)'));   //false
  • \W (大W)表示有一个非 数字 字母 下划线

const  reg=/\w/
  console.log(reg.test('1111'));   //false
	console.log(reg.test('dhasf')) ;   //false
  console.log(reg.test('-……&*(……)'));   //true
  • 点 (.)表示字符串里要有一个\n换行符就false 其他任意字符都true

 const  reg=/./
 console.log(reg.test('11\n11')); //true
 console.log(reg.test('\n')); //false
 console.log(reg.test('-……&*(……)')); //true
  • 斜线(\) 表示转义符 ,把没有意义的内容转换成有意义的内容,把有意义的内容转成没有意义的内容

 const  reg=/s/; //表示你的字符串里要有一个字母s
 console.log(reg.test('1111s')); //true

 const  reg=/\s/; //表示你的字符串里要有一个空格字符
 console.log(reg.test('1111s')); //false
 console.log(reg.test('1111 s')); //true

 const  reg=/./; //表示你的字符串里要有一个非换行的任意字符
 const  reg=/\./; //表示你的字符串里要有一个点 .文本

const reg=/\\/; 表示你的字符串里面要有一个斜线文本
 console.log(reg.test('1111s\\'));  //注意在字符串里面斜线也要转义 ,因为在字符串里面斜线也是转义

正则表达式的元字符 – 边界元字符

  • ^ (上尖角) 表示字符串开始
const reg=/^\d/; 表示你的字符串需要以一个数字开头
console.log(reg.test('1111s\\')); //true
  • $ 表示字符串结束

const reg=/\d$/; 表示你的字符串需要以一个数字结尾
console.log(reg.test('1111s\\2')); //true

const reg=/^\d$/;  表示字符串从开头到结尾只能有一个数字,一个\d,表示的是一个数字,一个符号只表示一个位置的文本内容

console.log(reg.test('1a2'));//false
console.log(reg.test('2'));//true

const reg=/^\d\d$/;  表示字符串从开头到结尾有2个数字,一个\d,表示的是一个数字
console.log(reg.test('1b2')); // fasle
console.log(reg.test('22')); //true

正则表达式的元字符- 限定元字符

限定元字符是写在普通元字符或者字母符号的后面,修饰前面 一个符号 的出现次数

  • 星 * 表示0 ~多次

const reg=/\d*/; //表示你的字符串里面需要出现一个 0到多个数字组成的片段
console.log(reg.test('12'));     //true
console.log(reg.test('asdf1yy2yy3'));  //true


const reg=/^\d*$/;  //表示你的字符串里面只能由 0到多个数字组成
console.log(reg.test('')); //true  数字出现0次
console.log(reg.test('12')); //true
console.log(reg.test('123')); //true
console.log(reg.test('1234')); //true
console.log(reg.test('asdf1yy2yy3')); //false
  • 加号 + 表示1 ~多次

const reg=/^\d+$/;  //表示你的字符串里面只能由 1到多个数字组成
console.log(reg.test('')); //fasle  数字出现0次
console.log(reg.test('12')); //true
console.log(reg.test('123')); //true
console.log(reg.test('1234')); //true
console.log(reg.test('asdf1yy2yy3')); //false
  • 问号 ? 表示0~1次

const reg=/^\d?$/; //表示你的字符串 只能由0 或者1 个数字组成
console.log(reg.test('')); //true
console.log(reg.test('1')); //true
console.log(reg.test('12')); //false
console.log(reg.test('asdf1yy2yy3')); //false
  • {n} 表示出现n次

const reg=/^\d{3}$/; //表示字符串只能由3个数字组成
console.log(reg.test('')); //false
console.log(reg.test('1')); //false
console.log(reg.test('12')); //false
console.log(reg.test('123')); //true
console.log(reg.test('asdf1yy2yy3')); //false
  • {n,} 表示出现 n~多次

const reg=/^\d{2,}$/; //表示你的字符串只能由2到多个数字组成
console.log(reg.test('')); //false 
console.log(reg.test('1')); //false 
console.log(reg.test('12')); //true
console.log(reg.test('123')); //true
console.log(reg.test('asdf1yy2yy3')); //false
  • {n,m} 表示指定出现n到m次

const reg=/^\d{2,3}$/; //表示你的字符串只能由2到3数字组成
console.log(reg.test('')); //false
console.log(reg.test('1'));  //false
console.log(reg.test('12')); //true
console.log(reg.test('123')); //true
console.log(reg.test('1244')); //false
console.log(reg.test('asdf1yy2yy3')); //false

{0,} 等价于*

{1,} 等价于+

{0,1} 等价于?

正则的贪婪与非贪婪
  • 贪婪:当你给一个符号使用限定符号的时候,在你捕获的时候,他会尽可能多的去捕获内容,我们管这个特性叫做正则的贪婪性

    const reg=/\d+/
    //在捕获的时候会捕获能捕获到的最大长度,就是123456789
    console.log(reg.exec('abc123456789abc')); 
    //  ['123456789', index: 3, input: 'abc123456789abc', groups: undefined]
  • 非贪婪:正则在捕获的时候尽可能的按照最小值来捕获,格式为 在写限定符的时候,在后面多加一个问号

    每一个限定符都可以在后面使用?

    const reg=/\d+?/  //?0~1
    //在捕获的时候会捕获能捕获到的最小长度捕获,就是1
    console.log(reg.exec('abc123456789abc'));
    // ['1', index: 3, input: 'abc123456789abc', groups: undefined]
    
    
    const reg=/\d*/
    console.log(reg.exec('abc123456789abc'));
    //['', index: 0, input: 'abc123456789abc', groups: undefined]
    console.log(reg.exec('123456789abc'));//从头开始找有数字就全部拿走,下一位是就不拿
    //['123456789', index: 0, input: '123456789abc', groups: undefined]
    
    const reg=/\d*?/
    //在捕获的时候会捕获能捕获到的最小长度捕获 
    console.log(reg.exec('abc123456789abc'));
    //['', index: 0, input: 'abc123456789abc', groups: undefined]
    console.log(reg.exec('abc123456789abc'));
    //['', index: 0, input: '123456789abc', groups: undefined]
    
    const reg=/\d?/
    console.log(reg.exec('123456789abc'));
    //['1', index: 0, input: '123456789abc', groups: undefined]
    const reg=/\d??/
    console.log(reg.exec('123456789abc'));
    //['', index: 0, input: '123456789abc', groups: undefined]
    
    const reg=/\d{3}/
    console.log(reg.exec('123456789abc'));
    //['123', index: 0, input: '123456789abc', groups: undefined]
    const reg2=/\d{3}?/
    console.log(reg2.exec('123456789abc'));
    //['123', index: 0, input: '123456789abc', groups: undefined]
    
    const reg=/\d{3,}/
    console.log(reg.exec('123456789abc'));
    //['123456789', index: 0, input: '123456789abc', groups: undefined]
    const reg2=/\d{3,}?/
    console.log(reg2.exec('123456789abc'));
    //['123', index: 0, input: '123456789abc', groups: undefined]
    
    
    const reg=/\d{3,7}/
     console.log(reg.exec('123456789abc'));
    //['1234567', index: 0, input: '123456789abc', groups: undefined]
    const reg2=/\d{3,7}?/
    console.log(reg2.exec('123456789abc'));
    //['123', index: 0, input: '123456789abc', groups: undefined]
    练习1:
     捕获一段 html 结构的字符串,捕获开始标签内的所有内容
     
    var str='<p style="color:red;"><span>yyyy</span></p>'
    const reg=/<.+>/
    console.log(reg.exec(str));
    //['<p style="color:red;"><span>yyyy</span><p>', index: 0, input: '<p style="color:red;"><span>yyyy</span><p>', groups: undefined]
    
    const reg2=/<.+?>/      //经常用来抓html结构时用的
    console.log(reg2.exec(str));
    //['<p style="color:red;">', index: 0, input: '<p style="color:red;"><span>yyyy</span></p>', groups: undefined]
    ----想匹配abcd
    练习2
    const reg3=/^abcd{2}$/;  表示abc d出现两次
    console.log(reg3.test('abcdabcd'));//false
     // 因为一个限定符只修饰它前面的一个符号或字母 {2}修饰的是d
    console.log(reg3.test('abcdabcdd'));//false
    console.log(reg3.test('abcdd'));//true
    
    const reg3=/abcd{2}/;
    console.log(reg3.test('abcdabcd'));//false 
    console.log(reg3.test('abcdabcdd'));//true
    console.log(reg3.test('abcdd'));//true
    
    
    
    
    const reg4=/a{2}b{2}c{2}d{2}/;
    console.log(reg4.test('abcdabcd')); //false
    console.log(reg4.test('aabbccdd')); //true
正则表达式的元字符-特殊字符
  • () 小括号

    • 表示一个整体

    const reg3=/(abcd){2}/;  //表示abcd这个整体出现两次
    console.log(reg3.test('abcdabcd'));//true 
    console.log(reg3.test('abcdabcdd'));//true
    console.log(reg3.test('abcdd'));//false
    • 单独捕获,单独将一些内容拿出来

      在你捕获一个字符串的时候,从左边开始每一个小括号依次是数组里面的[1]开始的内容

      从左向右依次数小括号的开始括号

    const reg6=/\d+\s+\d/;  //表示数字1到多个,空格(小S)一到多个,数字一到多个
    console.log(reg6.exec('123   123'));
    //['123   123', index: 0, input: '123   123', groups: undefined]
    
    const reg6=/\d+(\s+)\d+/;
    console.log(reg6.exec('123   123'));
    // ['123   123', '   ', index: 0, input: '123   123', groups: undefined]
    
    const reg6=/(\d+(\s+))\d+/;
    console.log(reg6.exec('123   123'));
    //['123   123', '123   ', '   ', index: 0, input: '123   123', groups: undefined]
    //索引0 为 '123   123'
    //索引1 为 '123   '
    //索引2 为 '   '
  • (?:) 表示整体匹配但不捕获,只是标志一个整体,但是捕获的时候不会单独捕获出来

const reg6=/\d+(?:\s+\d+){2}/;
console.log(reg6.exec('123   123 123'));
//['123   123 123', index: 0, input: '123   123 123', groups: undefined]
  • | 竖线, 占位或,表示左边或者右边的都行,大部分和()连用,表示一个整体或者一个整体

const reg7=/(abc|def)/;
console.log(reg7.test('abc'));//true
console.log(reg7.test('def'));//true
console.log(reg7.test('aaa'));//false
练习:
const reg7=/^abc|def$/; //表示以abc 或者 def结尾
console.log(reg7.test('abc'));//true
console.log(reg7.test('def'));//true
console.log(reg7.test('abc1233'));//true
console.log(reg7.test('1233def'));//true

const reg7=/^(abc|def)$/; 
console.log(reg7.test('abc'));//true
console.log(reg7.test('def'));//true
console.log(reg7.test('abc1233'));//false
console.log(reg7.test('1233def'));//false
console.log(reg7.test('abcdef'));//false

const reg7=/^ab(c|d)ef$/;  //表示的是字符串开头马上跟ab中间跟c或者d都可以,然后跟个ef字符串结尾
console.log(reg7.test('abc'));//false
console.log(reg7.test('def'));//false
console.log(reg7.test('1233def'));//false
console.log(reg7.test('abcdef'));//false
console.log(reg7.test('abcef'));//true
console.log(reg7.test('abdef'));//true
  • [] 中括号

    注意:一个[]占一个字符位置,表示里面任意一个都行

const reg9=/^[abcd]$/; //表示整个字符串只能由一个字符组成,可以是a b c d的任意一个
console.log(reg9.test('a'));//true

const reg7=/^[0-255]$/;// 表示的是 一个字符位置,可以0到2,或者 5 ,或者 5;
console.log(reg.test('0'));//true
console.log(reg.test('1'));//true
console.log(reg.test('2'));//true
console.log(reg.test('5'));//true
console.log(reg.test('3'));//false
  • [^] 一个[^]占一个字符位置 ,表示非里面的任意一个都行

const  reg6=/^[^abcd]$/; //表示你的字符串要由一份字符组成,只要不是a b c d中的任意一个就可以
console.log(111111,reg.test('a')); //false
console.log(2222,reg.test('1')); //true
  • (中划线)表示至 或者到的意思,是使用在[]里面的一个符号,表示从哪一个字符到哪一个字符,前提是他们在ASCII码是连着的

const  reg=/^[0-9]$/;
console.log(reg.test('0')); //true
console.log(reg.test('1')); //true
console.log(reg.test('2'));//true
console.log(reg.test('3'));//true
console.log(reg.test('a'));//false

const  reg2=/^[a-z]$/;//表示小写a 到小写z 
console.log(reg2.test('a')); //true
console.log(reg2.test('z')); //true
console.log(reg2.test('A'));//false
console.log(reg2.test('Z'));//false

const  reg3=/^[A-Z]$/;//表示大写a 到小写z 
console.log(reg3.test('a')); //false
console.log(reg3.test('z')); //false
console.log(reg3.test('A'));//true
console.log(reg3.test('Z'));//true

常见的组合形式

  • [0-9a-zA-Z_] 等价于 \w (小写w)

  • [^0-9a-zA-Z_] 等价于 \W (大写W)

  • [0-9] 等价于 \d

  • [^0-9] 等价于 \D

    [ ] 中括号里一个空格 等价于 \s

    [^ ] 中括号里一个^加一个空格 等价于 \S

特殊说明

当点(.)出现在 []或者 [^]里面的时候表示一个点文本而不再表示非换行的任意字符了

const reg4=/[123.]/;
console.log(reg4.test('1')); //true
console.log(reg4.test('2')); //true
console.log(reg4.test('3')); //true
console.log(reg4.test('.')); //true
console.log(reg4.test('a')); //false

小练习

const reg5=/^(abc|def){2}$/; //()圈起来一个整体,这个整体是abc 或者 def都性,{2}表示整体出现两次,只要有两个整体就可以,不论两次是不是一样
console.log(reg5.test('abcabc'));//true
console.log(reg5.test('defdef'));//true
console.log(reg5.test('abcdef'));//true
console.log(reg5.test('defabc'));//true
//需求:验证一个字符串,只能由数字字母下划线组成,6到12位,不能以_开头
const reg6=/^[a-zA-Z0-9]\w{5,11}$/;  //正确答案
const reg7=/^[^_]\w{5,11}$/;//这样不对,因为第一位只是控制了非_,但是没有控制是其他的特殊符号
console.log(111111,reg6.test('_ffffasd')); //false
console.log(2222,reg6.test('1ffffasd')); //true
需求:正则验证数字范围 0~255    
思路:
	把 0~255 的数字分成几类
	一位数                     \d  表示数字0到9
	两位数        							\d{2}  10 ~99
	1开头的三位数               1\d{2} 
	2开头 0~4的三位数          2[0-4]\d
	2开头 5的三位数             25[0-5]
	正则:
	/^(\d|\d{2}|1\d{2})|2[0-4]\d|25[0-5])$/
	/^(\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])$/   将上面的简化为下面的值
  /^(1?\d{1,2}|2[0-4]\d|25[0-5])$/       1有没有都行,后面带一位数或者两位数
  
  
const reg=/^(1?\d{1,2}|2[0-4]\d|25[0-5])$/
console.log(reg.test('9'));  //true
console.log(reg.test('199'));  //true
console.log(reg.test('245')); //true
console.log(reg.test('255')); //true
console.log(reg.test('256')); //false


//正则验证数字是一件很复杂的事情,验证数字一般不用正则我们可以直接使用 比较运算符来验证
正则表达式的预查
  • 正向预查

    • 正向肯定预查

      当我在捕获一个内容的时候,后面必须跟着是我选择的某一个才可以

      符号: (?=)

      //例子: ES2015  ES2016 ES2017 都是js的语法标准,正向肯定预查:我要捕获 后面必须写着 2015 或者 2016 的ES
      
      //正向肯定预查 字符串是ES205 或者 ES2016 是可以捕获的,但是我只捕获ES 不需要 2015 或者 2016
      const reg=/ES(?=2015|2016)/;
      console.log(reg.exec('ES2015'));  
      //['ES', index: 0, input: 'ES2015', groups: undefined]
      
      console.log(reg.exec('ES2016'));
      //['ES', index: 0, input: 'ES2016', groups: undefined]
    • 正向否定预查

      当我在捕获一个内容的时候,后面必须跟着不是我选择的某一个才可以

      符号: (?!)

      //正向否定预查 我只捕获ES 后面跟着的不是 2015 或者 2016
      const reg=/ES(?!2015|2016)/;
      console.log(reg.exec('ES2015')); //null 捕获不到
      console.log(reg.exec('ES2016')); //null 捕获不到
      console.log(reg.exec('ES2017'));
       //['ES', index: 0, input: 'ES2017', groups: undefined]
  • 负向预查

    • 负向肯定预查

      当我在捕获一个内容的时候,前面必须是我选择的某一个才可以

      符号: (?<=)

      const reg=/(?<=2015|2016)ES/;
      console.log(reg.exec('2015ES')); 
      //['ES', index: 4, input: '2015ES', groups: undefined]
      console.log(reg.exec('2016ES')); 
      //['ES', index: 4, input: '2016ES', groups: undefined]
      console.log(reg.exec('2017ES'));
      //nulljs
    • 负向否定预查

      当我在捕获一个内容的时候,前面必须不是我选择的某一个才可以

      符号:(?<!)

      const reg=/(?<!2015|2016)ES/;  //我还是要2015,但是前面的不能跟着2015 或者 2016 ,其他的都可以
      console.log(reg.exec('2015ES')); 
      //null
      console.log(reg.exec('2016ES')); 
      //null
      console.log(reg.exec('2017ES'));
      ////['ES', index: 4, input: '2017ES', groups: undefined]
重复出现 唯一可能出现的面试题
  • \num

    num是一个正整数; \1 \2 \3

    num是一个数字,表示的是正则第num个可被捕获的小括号(),这个可被捕获的小括号位置是什么 出现一份一模一样的内容

    const reg=/(abc|def)\d+/;
    console.log(reg.test('abc123')); //true
    console.log(reg.test('def1234')); //true
    
    const reg=/(abc|def)\d+\1/; //  \1表示重复出现第一个() 一模一样的内容一遍
    console.log(reg.test('abc123')); //false
    console.log(reg.test('def1234')); //false
    console.log(reg.test('abc123abc'));//true
    console.log(reg.test('abc123def'))//false
    console.log(reg.test('def123def'))//true
    
    const reg=/[abcd]\d+[abcd]\d+/;
    console.log(reg.test('a123b123')); //true
    
    const reg2=/([abcd])\d+[abcd]\d+\1/;
    console.log(reg2.test('a123b123'));//false
    console.log(reg2.test('a123b123a'));//true
    
    const reg3=/([abcd])\d+([abcd])\d+\1\2/;
    console.log(reg3.test('a123b123ab'));//true \1表示和第一个小括号的内容一样,\2表示和第二个小括号的内容一样
    
    const reg2=/(?:[abcd])\d+([abcd])\d+\1/; // \1 表示和第一个可被捕获的小括号一样,?:表示匹配但不捕获,所以重复的是第二个小括号里的值
    console.log(reg2.test('a123b123a'));//false
    console.log(reg2.test('a123b123b'));//true
const reg=/\d{2,4}/;//表示字符串里有2到4个连着的字符就可以
console.log(reg.test(''));//false
console.log(reg.test('1'));//false
console.log(reg.test('12'));//true
console.log(reg.test('123'));//true
console.log(reg.test('1234'));//true
console.log(reg.test('12345'));//true
console.log(reg.test('123456'));//true
/* 
需求验证一个邮箱
- 名字:9到15位,不能以_开头,只能由数字字母下划线组成
  只能是qq 163 sina邮箱
  后缀只能是 .com 或者 .cn


*/
const reg=/^[0-9a-zA-Z]\w{8,14}@(qq|163|sina)\.(com|cn)$/;
console.log(reg.test('340144299@qq.com'))
/* 
需求:
        我要能拿到手机号的运营商(通过手机号前3位的号端来判断运营商)
        +86有可能有有可能没有
        需要一个完整的手机号
        

        我的手机号是18737165345,我的生日是19890903

*/
const reg=/^(?:\+86 ?)?((187|185)\d{8})$/;
//? 有可能有,有可能没有,?: 匹配但不捕获  ()小括号单独捕获
console.log(reg.exec('18737165345'));
// ['18737165345', '18737165345', '187', index: 0, input: '18737165345', groups: undefined]

console.log(reg.exec('+86 18737165345'));
//['+86 18737165345', '18737165345', '187', index: 0, input: '+86 18737165345', groups: undefined]
console.log(reg.exec('+8618737165345'));
//['+8618737165345', '18737165345', '187', index: 0, input: '+8618737165345', groups: undefined] 



const reg2=/(?:\+86 )?((187|185)\d{8})/;
//有时捕获是在一段文本里拿,所以不要开头 结尾 ^$
console.log(reg.exec('我的手机号是:18737165345'));//null
console.log(reg2.exec('我的手机号是:18737165345'));
//['18737165345', '18737165345', '187', index: 7, input: '我的手机号是:18737165345', groups: undefined]
正则表达式的标识符

标志符是写在正则表达式外面,用来修饰整个正则表达式的

标识符:

  • i 忽略大小写

  • g 全局

  • 粘性全局

语法:/abcd/igy

new RegExp(‘abcd’,’igy’)

//----  is
const reg=/^[abcd]*$/;// * 为0到多个 
console.log(reg.test('abcd'));//true
console.log(reg.test('abcdA'));//fasle

const reg2=/^[abcd]*$/i;  //i 忽略大小写
console.log(reg2.test('abcd'));//true
console.log(reg2.test('abcdA'));//true
//-----  g 全局
/*
 匹配和捕获的时候,都是只能找到第一个
 当他又全局标识符的时候,你捕获的第二次会从第一次结束的位置开始查找
 直到找不到了返回null
 再后面一次的时候,又回到索引[0]的位置开始捕获
 匹配和捕获都是影响下一次开始位的
 
*/

const str='abc123abc456qbc789abc';
const reg=/\d{3}/;//在捕获的时候,不论执行多少遍都只能捕获到第一个
console.log(reg.exec(str));
console.log(reg.exec(str));
console.log(reg.exec(str));
//捕获三次拿到的都是123 ['123', index: 3, input: 'abc123abc456qbc789abc', groups: undefined]
const reg2=/\d{3}/g;
//当有全局标识符,你捕获第二次的时候会从第一次的结束为开始查找
console.log(reg2.exec(str));
//结束为是索引[5]   
//['123', index: 3, input: 'abc123abc456qbc789abc', groups: undefined]
console.log(reg2.exec(str));
//查找的开始位是索引[6] ,捕获到的开始位是[9] ,捕获到的结束位是[11]  
//['456', index: 9, input: 'abc123abc456qbc789abc', groups: undefined]
console.log(reg2.exec(str));
//第三次查找的开始位是索引[12] 捕获到的开始位是[15] ,捕获到的结束位是[17]
//['789', index: 15, input: 'abc123abc456qbc789abc', groups: undefined]
//直到找不到了,返回null
console.log(reg2.exec(str));
//查找开始位是18,找不到了就返回null
console.log(reg2.exec(str));
//再后面一次的捕获,又回到索引[0]位置开始捕获
//g的匹配和捕获都是影响开始位的
//------ y 粘性全局
const str='abc123abc456qbc789abc';
const reg2=/\d{3}/g;
console.log(reg2.exec(str)); //g 123
const reg3=/\d{3}/y;
console.log(reg3.exec(str)); //null 
//粘性捕获的时候 第一次必须是从索引位0的位置就刚好能捕获到内容 ,第二次必须是从第一次结束位开始就刚好能捕获到内容才可以


const str2='123456789abc';
const reg2=/\d{3}/y;

console.log(reg2.exec(str2));
//['123', index: 0, input: '123456789abc', groups: undefined]
console.log(reg2.exec(str2));
//['456', index: 3, input: '123456789abc', groups: undefined]
两种创建正则表达式的区别
  • 字面量创建正则表达式

    语法:var reg=/abcd/igy;

    区别:1不能进行字符串的拼接

    2 在书写基础元字符的时候直接写\xx

    //-------------1不能进行字符串的拼接
    //验证字符串good
    const reg=/good/;//验证字符串good,只能这样写,不能使用变量
    var str='good';
    const reg2='/'+str+'/';//这样得到的是字符串‘good’而不是正则,不能使用正则的test 和 exec 方法
    console.log(reg2)
    //-------------在书写基础元字符的时候直接写\xx
    const reg=/\d\s\w/;//得到正则 /\d\s\w/
  • 内置构造函数创建正则

    语法:var reg=new RegExp(‘abcd’,’igy’);

    区别 :1 可以进行字符串的拼接

    2 在书写基础元字符的时候要写 \\xx

    //-------1 可以进行字符串的拼接
    var str='good';
    const reg2=new RegExp(str);//返回正则 /good/
    
    const reg2=new RegExp('go'+'od');//返回正则 /good/
    
    //这是因为该构造函数的第一参数就是要传一个字符串,我们使用变量或者使用字符串的拼接操作
    //------在书写基础元字符的时候要写 \\\xx
    const reg2=new RegExp('\s\d\w');//得到正则 /sdw/
    //这是因为在字符串里也有转义字符,也是\ ,比如当在书写n的时候,表示文本 n ,当在书写\n的时候,表示换行的意思,当你在字符串里书写\s的时候,他会把s转换成有意义的内容,但是\s确实没有实际意义,所以就变成一个普通s文本  在字符串里就是一个普通的s文本
    console.log('s','\s');//s s 
    //所以我们的正则应该这样写
    const reg3=new RegExp('\\s\\d\\w');/得到正则 /\s\d\w/
//练习1
//捕获一个字符串里面所有三位数
var str='dssdf123sdghf456hadsjf789adsf'
//结果是 123 456 789
var reg=/\d{3}/g;
//先捕获一次看看能不能捕获到,返回null则说明一次都没有,不为null则是可以捕获到得到,则将捕获到的数据放到一个数组里,再进行下一次捕获
var tmp=reg.exec(str);
var res=[];//准备一个空的数组存贮捕获到到的数据
while(tmp){
    res.push(tmp[0])
    tmp=reg.exec(str);//进行下一次捕获,重新给tmp赋值,好进行下一次的判断
}
console.log(res);//['123', '456', '789']9
知识点补充

字符串和正则合作的方法这些方法都是字符串的方法,只不过参数位置可以写正则

  • 字符串对象的search方法,返回第一个满足条件的匹配结果在整个字符串中的位置,如果没有任何匹配,则返回-1

    语法: 字符串.search(字符串片段) 字符串.search(正则表达式) 返回值:如果有就是对应的索引,如果没有就是返回-1

'_x_x'.search(/x/);//1
'sdfs123sddd'.search('123');
'sdfs123sddd'.search(/\d{3}/);
  • 字符串对象的replace方法可以替换匹配的值,他接受两个参数,第一个是正则表达式,表示所有模式,第二个是替换掉内容

    语法: 字符串.replace(字符串片段,要替换的内容) 返回值:只能替换第一个查找到的内容,返回替换好的字符串 字符串.replace(正则表达式,要替换的内容) 返回值:没有全局标识符g的时候,只能替换第一个查找到的内容,返回替换好的字符串,有全局标识符时候,会把字符串内所有满足正则规则的内容全部替换,返回替换好的字符串

'aaa'.replace('a','b');//'baa'
'aaa'.replace(/a/,'b');//'baa' 
'aaa'.replace(/a/g,'b');//'bbb' 全局替换
'aaa'.replaceAll(/a/g,'b');//js没有
//练习2
//全部替换字符串内的三位数为**
//一旦你有了全局表示符g直接使用replace即可



var str='dssdf123sdghf456hadsjf789adsf'
console.log(str.replace(/\d{3}/g,'**'));//dssdf**sdghf**hadsjf**adsf 不会修改原字符串
  • match()

    语法:字符串.match(字符串片段);

    返回值:查找到字符串内一个满足字符串片段的内容返回,返回格式和exec一模一样

    字符串.match(正则表达式);

    返回值:当正则表达式没有全局标识符g的时候,返回值和exec方法一模一样

    当正则表达式有全局标识符g的时候,返回一个数组,里面是所有满足条件的内容

var newStr='hello word 你好 hello word 你好hello word 你好hello word 你好';
console.log(newStr.match('你好'));
//['你好', index: 11, input: 'hello word 你好 hello word 你好hello word 你好hello word 你好', groups: undefined]
console.log(newStr.match(/你好/));
//['你好', index: 11, input: 'hello word 你好 hello word 你好hello word 你好hello word 你好', groups: undefined]
console.log(newStr.match(/你好/g));
//['你好', '你好', '你好', '你好

//---匹配中文
console.log(newStr.match(/[\u4e00-\u9fa5]/g));
//['你', '好', '你', '好', '你', '好', '你', '好']
console.log(newStr.match(/[\u4e00-\u9fa5]+/g));  //+表示一次到多次
//['你好', '你好', '你好', '你好']
  • 正则匹配中文

    在正则表达式里面\u 表示查找中文,后面要带上中文的四位 unicode编码。但是我们不知道每一个中文的所对应的unicode编码,所以我们可以些一个范围

    [\u4e00-\u9fa5] 表示任意一个中文字符

案例:表单验证
//需求
        /* 
        表单验证:
        随着用户的输入,随时进行表单验证
        文本框右侧有一个字体图标,用户输入满足条件时显示对勾,否则显示叉(学生写)
        文本框下显示用户输入的规则:非下划线开头,只能由数字字母下划线组成,6~8位
        有一段文本提示,当不满足的时候显示的文本内容为红色
        
        
        */