正则

创建 两种方式

  • 1、 直接量定义 /正则/修饰符
  • 2、 对象定义 new RegExp(字符串,修饰符)
    • 传递的是字符串,需要对特殊字符进行双重转义

对比

  字面量模式         等价的字符串
  /\[bc\]at/  =>  "\\[bc\\]at"
  /\d.\d{1,2}/  =>  "\\d.\\d{1,2}"

  let path = '/user/:uid/:name';
  let reg1 = /\:\w+/g
  console.log(reg.source) => \:\w+
    
  // 这里注意 \\w  我们要他的\  里所有的第一个\代表转义 最终我们要得到(\w) 所以就是\\  
  let reg2 = new RegExp('\:\\w+', 'g')

修饰符

  • 常用的就i忽略大小写,g全局匹配

转义字符

  \  转义符
  \n 换行(newline)
  \s 空格(space)
  \S 非空格
  \' 单引号
  \" 双引号
  \d (digit)数字,正则中专门用来代表数字的,等级于 [0-9]
  \D 非数字字符,等价于[^0-9]
  \w 数字、字母、下划线
  \W 非数字、非字母、非下划线
  \b 单词的边界,独立的部分(起始位子、结束位子、空格),它不匹配某个可见的字符,而是匹配位子(border)
  \B 非边界的部分
  .  任意一个字符
  \. 真正的点  匹配除\n换行以外的任意单字符  匹配包括\n在内的所有字符  使用(.|\n)

量词


所有的量词都需要放在{n,m}里面
n,m代表数字

{n}     前一项重复n次
{n,}    前一项至少重复n次,最多不限
{n,m}   前一项至少重复n次,最多重复m次

+      前一项至少重复1次,最多不限     等价{1,}
?     前一项至少重复0次,最多重复1次,也就是说前一项是可选的,等价于{0,1}
*      前一项至少重复0次,最多不限,也就是说前一项是可选的,等价{0,}

^      它出现在中括号里代表排除的意思,在中括号的外面标示字符串开始的位子
$      字符串结束的位子

正则属性

  • 正则对象的属性
    • $n n代表()内匹配数据
    • RegExp 对象上的方法 RegExp.$n
      • 在replace方法里用 RegExp.$1 匹配的都是最后一个 可以用 arguments[n] 获取,但是不要用箭头函数(无arguments)
      • 当正则 匹配后就可以用(不匹配拿不到) RegExp.$n 匹配分组的数据 n代表数字 1代表第一个分组
  • 正则原型上的属性
  global 布尔值,表示是否设置了g标志
  ignoreCase 布尔值,表示是否设置了i标志
  lastIndex 整数,表示开始搜索下一个匹配项的字符位置,从0开始(带g才有效果 不然每次都是从头开始)
  multiline 布尔值 表示是否设置了m表示
  source 正则表达式的字符串表示
  var pattern = /\[bc\]at/i;
  console.log(pattern.global) => false
  console.log(pattern.ignoreCase) => true
  console.log(pattern.multiline) => false 
  console.log(pattern.lastIndex) => 0
  console.log(pattern.source) => "\[bc\]at"

正则方法

  • 匹配规则:默认前一项的结束是下一项的开始
      exec 匹配内容
        不带g
          功能和match 是一样 第一个是匹配的内容 第二个是分组内容
        带g
          match 带g 返回的数组 全是匹配的内容 和不带g返回的 完全不一样
          exec 要执行一次 和 不带是一样的 只会匹配到第一个 
             再次 执行的时候 会匹配到第二个(索引和匹配的内容 跟着变化), 他们返回的数据格式 和不带g是一样的
        let str = '/url1/:id/:name'
        let reg = /\:([^\/]+)/g
        let a = reg.exec(str)
        let b = reg.exec(str)
        console.log(a, b)
      test
        正则.test(str)
        返回布尔值
    

字符串方法使用正则

  • match 和 exec 主要是做匹配数据 replace 也可以匹配数据 但他主要是做替换
  match 匹配内容
    不带g 返回数组 第一个是匹配的内容 第二个开始 就是()内的匹配内容 index/input等 以文本下标显示不占数字的length 
          在使用数组方法的时候 文本下标 不会循环出来
          小技巧: 在多个分组的时候 索引从一开始到最后 全是分组内容
      
    带g   返回数组 里面全是匹配的内容
    let str = '/url1/:id/:name'
    let reg = /\:([^\/]+)/
    let match = str.match(reg)
    console.log(match)
  replace   
    函数接收的参数 (返回替换后的内容,原来的不变) 
      第一个是匹配到的内容 
      第二个是分组匹配的内容(若多个分组 下面的索引往后靠,要是没有就往前挪)
      第三个是索引
      第死个是原字符串
    let str = '/url1/:id/:name'
    let reg = /\:([^\/]+)/
    str.replace(reg, function($1, $2, $3, $4) {
        console.log($1, $2, $3, $4)
    })
  split 
    用来切割字符串 将字符串转换成数组
    第一个可以是字符串 也可以是 正则

中括号

[]              匹配中括号里的任意一个字符,只代表一个字符
[1-9]           区间的写法,标示从19之间的任意的一个字符
[a-z]           a-z之间的任意一个小写字母
[A-Z]           A-Z之间的任意一个大写字母 
[a-zA-Z0-9]     匹配a-z,A-Z,0-9(匹配任何字母和数字)
^               排除掉某个字符(仅仅用在中括号内表达这个意思)
[\u4e00-\u9fa5] 中文的区间,包含所有的汉字

red|blue|green 标示red,blue,green 这三个单词中的任何一个(至少)

量词种类

贪婪

  • 尽量多的匹配
    • ?匹配0或者1个 贪婪模式先匹配1个 当1匹配不到的时候 在从上一次匹配的下一个位子开始 匹配0
    • *匹配0或者至多个 规律同上
    • +匹配1或者至多个 规律同上
    • x{n,m} 和 x{n,} 同上
  • x?
       aaa  a?a => aa a
    
  • x*
       aaa  a*a => ['aaa']
       aaa1a  a*a => ['aaa','a']  
    
  • x+
       aaa  a+a => ['aaa']
       aaa1a  a+a => ['aaa']
       aaa1aa  a+a => ['aaa','aa']
    
- x{n,m}  x{n,}
  -  同上 例子就写了
### 懒惰
- 尽量少匹配
- x??
  ```js
    aaa  a??a =>  ['a','a','a']
  ```
- x*?
  ```js
    aaa a*?a => ['a','a','a']
  ```
- x+?
  ```js
    aaa a+?a => ['aa']
  ```
## 捕获组
-  捕获组:使用括号作为单独的单元来对待的一种方式,可通过程序方便地拿到分组对应的匹配内容
- (\d\d)\1 == (\d\d)\d\d  也就是说是一个ABAB形式的
```js
// 1、匹配连续出现的数字
let str = 'aa1212ss'
let rs = str.match(/(\d\d)\1/g)
console.log(rs) => [1212]
// 2、匹配html标签
let str = '<div id='ss'><a>123</a></div>'
let rs = str.match(/<([a-z]+).+?<\/\1>/)
console.log(rs)

非捕获组

  • 分组括号里第一个是?就是非捕获组(不计算在分组内)
  • 好处 不会讲匹配到的字符存储在内存种 从而节省内存
  • 一般常用的就是 (?:xxx)
let str = 'ad123asd'
let rs = str.match(/(?:\d)/)
console.log(rs) // 结果没有分组的内容 数组长度是1

?=

  • 前瞻 exp1(?=exp2) 查找exp2前面的exp1
  • 后顾 (?<=exp2)exp1 查找exp2前面的exp1(js不支持)
  • 负前瞻 exp1(?exp2) 查找后面不是exp2的exp1
  • 负后瞻 (?<!exp2)exp1 查找前面不是exp2的exp1(js不支持)