1. 作用

  • 用来匹配字符串中字符组合的模式
    • 表单验证(匹配)
    • 过滤敏感词(替换)
    • 从字符串中获取特定部分(提取)

2. 创建

  • 字面量方式创建

    • 简单、直观,最常用
      1. let reg = /^\+86\d{11}$/
  • 构造函数方式创建

    • 麻烦,但正则规则可通过字符串拼接,有些场景不得不用
      let reg = new RegExp('^\\+86\\d{11}$')
      
  • 最后的g代表全局,还有几个修饰符

    • g:global,全文搜索,不添加的话搜索到第一个结果停止搜索
    • i:ignore case,忽略大小写,默认大小写敏感
    • m:multiple lines,多行搜索

      3. 简单用法

  • 正则的方法

    • 判断给定字符串是否符合正则规则
      // 判断字符串中的是否含有连续11位数字
      let reg = /\d{11}/
      let str1 = '13087984989'
      let str2 = 'a12034345453a'
      let str3 = '123234aa343434'
      console.log(reg.test(str1))     // true
      console.log(reg.test(str2))     // true
      console.log(reg.test(str3))     // false
      
  • 字符串方法 ```javascript let str = ‘hello1 aaaaaaa, hello2 bbbbbb’

// 搜索 返回第一个索引 str.search(/hello\d/) //0

// 匹配 返回由匹配的字符串组成的数组 str.match(/hello\d/g) //[‘hello1’, ‘hello2’]

// 替换 返回新的字符串 str.replace(/hello\d/g, ‘hi’) // “hi aaaaaaa, hi bbbbbb”

// 分割 返回数租,\s表示用空格分割 str.split(/\s/) //[“hello1”, “aaaaaaa,”, “hello2”, “bbbbbb”]

<a name="KBsry"></a>
# 4. 匹配

- **具有特殊意义的字符**
   - 如果要匹配这些特殊字符,需要转义

![image.png](https://cdn.nlark.com/yuque/0/2020/png/2205407/1599723097855-6662270c-5261-44f3-a99b-ada8c9be6b9d.png#height=58&id=vroYf&margin=%5Bobject%20Object%5D&name=image.png&originHeight=63&originWidth=506&originalType=binary&ratio=1&size=3420&status=done&style=none&width=469)
```javascript
// 判断字符串中包含了多少个 "."
let str = '. s. .r .9. 4k. 3.efef.er'
let res = str.match(/\./g).length
console.log(res)     // 8


  • 字符匹配(很少用)

    let reg = /hello/
    reg.test('chm hello afd')  // true
    
  • 范围匹配

    • [abcd] 匹配一个字符,是a b c d中的任意一个
    • [0-9] 匹配一个是0到9的数字
    • [a-zA-Z]匹配一个不限制大小写的字母
    • [^abc] 表示一个不是字符a或b或c的字符
    • /^[abc]$/表示三选一,只有是a或者b或者c才符合
      let reg = /不要[89][89][67]/
      reg.test('我们不要996')     // true
      reg.test('我们不要899')    // false
      
  • 预定义匹配

    • . 等价于 [^\r\n],匹配一个除回车和换行以为的任意字符
    • \d 等价于[0-9],匹配一个数字字符
    • \D 等价于[^0-9], 匹配一个非数字字符
    • \s 等价于[空格\t\n\r\v\f],匹配一个空白字符
    • \S 等价于[^空格\t\n\r\v\f],匹配一个非空白字符
    • \w 等价于[a-zA-Z_0-9],匹配一个字母、数字、下划线
    • \W 等价于[^a-zA-Z_0-9],匹配一个非单词字符

      5. 量词

  • 匹配0个到多个

    • 前面的字符出现0次或者1次
    • + 前面的字符出现1次或者多次
    • * 前面的字符出现0次或者多次
    • {n} 前面的字符出现n次
    • {n,m} 前面的字符出现n到m次
    • {n,} 前面的字符出现至少n次
      let str1 = 'http://baidu.com'
      /https?:\/\/.+/.test(str1) // true
      /https+:\/\/.+/.test(str1) // false
      /https*:\/\/.+/.test(str1) // true
      

      6. 边界

  • 以…开头或者以…结尾

    • /^xyz/ 以xyz开头
    • /abc$/ 以abc结尾
    • /^abc$/ 只能有abc三个字符
    • /\babc\b/ 匹配是单词的abc(左右两侧是字符串开头、 结尾、中横线、空格)
    • /\Babc\B/ 匹配不是单词的abc ```javascript var str1 = ‘hello1 world hello2 123456 hello3’ str1.match(/hello\d/g) // [“hello1”, “hello2”, “hello3”] str1.match(/^hello\d/g) // [“hello1”] str1.match(/hello\d$/g) // [“hello3”]

var str2 = ‘hello1 whello9orld hello2 12-hello8-3456 hello3’ str2.match(/\bhello\d\b/g) //[“hello1”, “hello2”, “hello8”, “hello3”]

<a name="Q4NIl"></a>
# 7. 案例

- **匹配手机号**
   - 判断用户的输入是否符合手机号规则
   - 规则:以1开头长度为11的数字
   - 验证是为了防止用户误操作,不是越严格越好
```javascript
let reg = /^1\d{10}$/
reg.test(' 13189890989') // false
reg.test('a13189890989b') // false
reg.test('13189890989') // true
reg.test('1318989098910') // false
  • 匹配邮箱

    • 判断用户的输入是否符合邮箱规则
    • 规则:字符串中间包含一个@,@后面包含一个 .
      let reg = /^[^@\s]+@[^@\s]+\.[^@\s]+$/
      reg.test('hr@abc.com) // true
      reg.test('admin@jirengu.中国')  // true
      reg.test('abc@cdd@jirengu.cn') // false
      reg.test('abc@j rengu.com')    // fasle
      
  • 匹配用户名

    • 判断用户的输入是否是合法用户名
    • 规则:合法用户名至少8位至多15位,包含大写、小写、 数字、下划线至少两种
    • 写正则不是目的,解决问题才是目的 ```javascript function validUsername(rawInput) { //如果 不 满足 全部为字母数字下划线且长度为8~15 返回false if(!/^\w{8,15}$/.test(rawInput)) { return false }

    // 如果只包含一种 返回false if(/(^[a-z]+$)|(^[A-Z]+$)|(^[0-9]+$)|(^_+$)/.test(rawInput)) { return false }

    return true } ```

    8. 贪婪模式与非贪婪模式

  • 问题1

    • ‘123456789’.match(/\d{3,5}/g) 的结果是什么?
    • 是 [‘123’ , ‘456’ , ‘789’] 还是 [‘12345’ , ‘6789’] ?
  • 解答

    • 默认是贪婪模式,即尽可能多的匹配。如果想使用非贪婪模式,可以再量词后加 ? 即可
      let str = '123456789'
      let res = str.match(/\d{3,5}/g)
      console.log(res)      // ["12345", "6789"]
      
  • 问题2

    • aa"hello world" ok "jirengu".match(/“.+”/g) 的结果是什么?
    • 如何匹配得到双引号里面的内容?
  • 解答 ``javascript let res1 =aa”hello world” ok “abc”`.match(/“.+”/g) console.log(res1) // [“”hello world” ok “abc””]

let res2 = aa"hello world" ok "abc".match(/“.+?”/g) console.log(res2) // [“”hello world””, “”abc””]

<a name="6aok0"></a>
# 9. 分组

- **把一些字符作为一个整体**
```javascript
//匹配 abcdeee ,而不是 abcdeabcdeabcde
/abcde{3}/

//把abcde作为一个整体,匹配 abcdeabcdeabcde
/(abcde){3}/

//匹配 “hello world” 和 “hi world”
/(hello)|(hi) wolrd/

//$1代表正则里分组匹配的内容,输出 “hi8 world, hi6 abc”
"hello8 world, hello6 abc".replace(/hello(\d)/g, 'hi$1')
// 将字符串中的div标签换为span标签
let str = '<div>this is div</div>'
let res = str.replace(/(<\/?)div(>)/g, '$1span$2')
console.log(res)     // "<span>this is div</span>"
// 把字符串中的div标签替换成span标签
let str = `
<div class="container">
  <div class="box"> 我是div </div>
</div>
`
let str2 = str.replace(/(<\/?)div(.*?>)/g,'$1span$2')
console.log(str2)

/*输出
<span class="container">
  <span class="box"> 我是div </span>
</span>
*/

10. 前瞻

image.png

// 匹配hello后面有一个数字并且数字后面是 world的子字符串
let str = 'hello5 world, hello world hello6world'
let res = str.match(/hello\d(?= world)/)
console.log(res)        // ["hello5"]