JS 正则表达式

114 阅读6分钟

正则表达式

  • 正则表达式, 又名 "规则表达式"
  • 由我们自己来书写 "规则", 专门用来检测 字符串 是否符合 "规则" 使用的
  • 我们使用一些特殊的字符或者符号定义一个 "规则公式", 然后用我们定义好的 "规则公式" 去检测字符串是不是合格

构建正则表达式

  • 想制定 "规则", 就必须要按照人家要求的方式来制定
  • 把一些字母和符号写在 // 中间的东西, 叫做正则表达式, 比如 \abcdefg\
  • 创建正则表达式有两个方式 字面量构造函数创建

字面量方式

var reg = /abcdefg/
=>  `//`内部可以书写任何表达式

构造函数创建

var reg = new RegExp('abcdefg')
=>  '' 内部可以书写任何表达式

两种创建方式的区别

  1. 书写标识符
  • 字面量方式,直接在正则后书写表示符 let reg1 = /abc/ig
  • 内置构造函数的方式,需要写在第二个参数中 let reg2 = new RegExp('abc','ig')

2.书写元字符

    let reg1 = /\d\w\s.\./
    console.log(reg1)  // --> /\d\w\s.\./
    let reg2 = new RegExp('\d\w')
    console.log(reg2)  //--> /dw/

在字符串中,如果书写了 \ 那么相当于转义符,将后边的字符转换为_有意义的字符 但是转换完成以后, \ 就会自动消失.那么正则拿到的就是一个具有特殊含义的字符d

但是又因为正则中元字符必须是\+d结合在一起才是一个元字符, 如果只有一个d那么就是一个普通的字母,没有任何特殊含义

解决方法:

在原本的 \ 前面再加一个 \ 第一个\将第二个 \ 转换为没有任意义的 普通义本。 最终正则拿到的就是一个没有特殊含义的 +d 然后按照正则的规则中, \+d 就是一个元字符。代表的是数字0-9

    let reg2 = new RegExp('\d\w')
    console.log(reg2)  //--> /\d\w/

正则的常用符号

元字符

  • .: 匹配非换行的任意字符

  • \: 转译符号, 把有意义的 符号 转换成没有意义的 字符, 把没有意义的 字符 转换成有意义的 符号

  • \s: 匹配空白字符(空格/制表符/...)

 var reg = /\s/
 var reg = /\S/
 console.log(reg.test('1515%%#'))//false
 console.log(reg.test(' as as'))//true
 console.log(reg.test('  '))//true
  • \S: 匹配非空白字符
  • \d: 匹配数字
var reg = /\d/
var str1 = 'ab'
var str2 = 'abc123'
var str3 = 'abc12315'
console.log(reg.test(str1))   =>  false
console.log(reg.test(str2))   =>  true
console.log(reg.test(str3))   =>  true
  • \D: 匹配非数字
  • \w: 匹配数字字母下划线
  • \W: 匹配非数字字母下划线

边界元字符

边界符是限定字符串的开始和结束的

  • ^: 表示开头
  • $: 表示结尾
var reg = /^\d{3,5}$/
var str = 'abc'
var str2 = 'abc123'
var str3 = '1'
var str4 = '1234567'
var str5 = '123'
var str6 = '12345'
console.log(reg.test(str))  // false
console.log(reg.test(str2))  // false
console.log(reg.test(str3))  // false
console.log(reg.test(str4))  // false
console.log(reg.test(str5))  // true
console.log(reg.test(str6))  // true

限定元字符

限定 前一个符号 出现多少次

  • * 表示出现 0 ~ 正无穷次
  • + 表示出现 1 ~ 正无穷次
  • ? 表示出现 0 ~ 1 次
  • {n} 表示出现 n 次
  • {n,} 表示出现 n ~ 正无穷次
  • {n,m}表示出现 n ~ m 次

特殊符号

  • () 表示限定一组元素
  1. 含义: 单独捕获;
  2. 含义: 一个整体;
  • | 或; 含义: a|b 表示 a或者b
  • [] 字符合集, 表示包含 [] 中的任何一个元素都可以,只要满足其中一个即可
  • [^] 非字符合集,即不包含 [^] 中的某一个就行
  • - 到;至 ; 通常和[],[^]连用,
  1. [0-9] 表示数字09,  等价于 \d
    
  2. [^0-9] 表示不包含数字09,  等价于 \D
    
  3. [a-z] 表示小写字母a到z
    
  4. [0-9a-zA-Z_]    等价于 \w
    

或的分界线

或的分界线为 小括号 或者 正则的边界

 var reg = /^abc|def$/
  //解析;满足  ^abc  或者  def$  且只有三位
 console.log(reg.test('abc1546'))    //true
 console.log(reg.test('151abc1546'))    //false

    
var reg = /^ab(c|d)ef$/
//解析;满足  c  或者  d   且只有5位
console.log(reg.test('abcef'))    //true
console.log(reg.test('abdef'))    //true
console.log(reg.test('abcdef'))   //false

重复元字符

  • 语法: 符号: \数字 数字代表第几个小括号
  • 含义:表示重复第n个小括号的内容,并且要求和小括号的内容完全一致
 var reg = /^(abc|def)\1$/
 console.log(reg.test('abcabc'))   //true
 console.log(reg.test('abcdef'))   //false
 console.log(reg.test('defdef'))   //true
  • 小案例:

需求,字符串是span或者p标签

var reg = /<(span|p)><\/\1>/
console.log(reg.test('<span></span>')) 

标识符

  • 写在表达式外面
  • 用来描述整个正则表达式的
  1. i
    表示忽略大小写
  1. g
    表示全局
var reg = /^[abcd]$/i
console.log(reg.test('a'))//true
console.log(reg.test('A'))//true
console.log(reg.test('n'))//false

捕获(还账)

语法: 正则.exec(字符串)

  1. 字符串没有符合正则规则的内容

捕获结果为null

 var reg = /\d{3}/
 console.log(reg.exec('abc'))//null
  1. 正则没有小括号,没有标识符 g

捕获到是一个数组,下标零是我们捕获到的值, 但是无论捕获多少次,都是从头开始第一个满足条件的

var reg = /\d{3}/
console.log(reg.exec('123abcd'))//[123]
  1. 有小括号

下标0 是符合正则规则的字符串 , 从下标1 开始是每个小括号捕获的数据

var reg = /(\d{3})(\w{3})(\d{3})/
console.log(reg.exec('123abc456'))
// ['123abc456', '123', 'abc', '456', index: 0, input: '123abc456', groups: undefined]
  1. 有全局标识符

第二次捕获时会从第一次捕获结束的位置开始捕获, 直到找不到内容会返回null, 再下一次捕获会重新开始,

var reg = /(\d{3})/g
    console.log(reg.exec('123abc456'))//[123]
    console.log(reg.exec('123abc456'))//[456]
    console.log(reg.exec('123abc456'))//null
    console.log(reg.exec('123abc456'))//[123]

正则两大特性(面试常问)

1.懒惰

  • 每次捕获都是在下标0 的位置开始
  • 解决: 在正则后添加 g
  1. 贪婪
  • 每次捕获内容时尽可能多去捕获内容
  • 解决:使用非贪婪限定符
  • 在原有的限定符后面添加一个 ?
    •    贪婪限定符:        非贪婪限定符:
      
    •    *                    *?
      
    •    +                    +?
      
    •    ?                    ??
      
    •    {n}                 {n}?
      
    •    {n,}                {n,}?
      
    •    {n,m}               {n,m}?
      
var str = `<div class="box" id="box"><span></span></div>`

// 贪婪捕获
var reg = /<div.*>/
console.log(reg.exec(str))
// => <div class="box" id="box"><span></span></div>

// 非贪婪捕获
var reg1 = /<div.*?>/
console.log(reg1.exec(str))
// => <div class="box" id="box">

字符串的方法

字符串中有一些方法是可以和正则一起使用

search: 查找字符串中是否有满足条件的内容

  • 语法: 字符串.search(正则)
  • 返回值: 有的话返回开始索引, 没有返回 -1
var reg = /\d{3}/
var str1 = 'hello123'
var str2 = 'hello'
console.log(str1.search(reg))   // 5
console.log(str2.search(reg))   // -1

match: 找到字符串中符合正则条件的内容返回

  • 语法: 字符串.match(正则)
  • 返回值:
    • 没有标识符 g 的时候, 是和 exec 方法一样
    • 有标识符 g 的时候, 是返回一个数组, 里面是匹配到的每一项, 没有匹配到内容是返回的是 null
var reg = /\d{3}/
var str1 = 'hello123world456'
var str2 = 'hello world'
console.log(str1.match(reg))
/*
['123', index: 5, input: 'hello123world456', groups: undefined]
    0: "123"
    groups: undefined
    index: 5
    input: "hello123world456"
    length: 1
*/
console.log(str2.match(reg))    // -1
var reg = /\d{3}/g
var str1 = 'hello123world456'
var str2 = 'hello world'
console.log(str1.match(reg))    // ['123', '456']
console.log(str2.match(reg))    // null

replace: 是将字符串中满足正则条件的字符串替换掉

  • 语法: 字符串.replace(正则, 要替换的字符串)
  • 返回值: 替换后的字符串
var reg = /\d{3}/
var str1 = 'hello123world456'
var str2 = 'hello world'
console.log(str1.replace(reg, '哈哈哈哈'))    // hello哈哈哈哈world456
console.log(str2.replace(reg, '哈哈哈哈'))    // hello world
var reg = /\d{3}/g
var str1 = 'hello123world456'
var str2 = 'hello world'
console.log(str1.replace(reg, '哈哈哈哈'))    // hello哈哈哈哈world哈哈哈哈
console.log(str2.replace(reg, '哈哈哈哈'))    // hello world