正则表达式是匹配模式,要么匹配字符,要么匹配位置。能够实现模糊匹配。

  1. 横向模糊匹配:正则可匹配的字符串的长度是不固定的
  2. 纵向模糊匹配:正则匹配的字符串,具体到某一位数字时,他可以不是某个确定的字符,可以用多种可能。

匹配字符

字符组

量词

匹配位置

符号 含义
^ 匹配开头,在多行匹配中匹配行开头
$ 匹配结尾,在多行匹配中匹配行结尾
\b \b 是单词边界, 具体就是 \w 与 \W 之间的位置, 也包括 \w 与 ^ 之间的位置, 和 \w 与 $ 之间的位置。
\B \B 就是 \b 的反面的意思,非单词边界。例如在字符串中所有位置中,扣掉 \b,剩下的都是 \B 的。
(?=p) (?=p), p 是子模式,即 p 前面的位置
(?! p) 与 (?=p) 相反,即非 p 前面的位置
(?<=p) 只有在 p 后面才匹配
(?<! p) 匹配非 p 后面位置,和上面相反

括号

括号提供子表达式,强调括号内的正则是一个整体。

  1. 分组
  2. 分支结构

分组引用

分组引用比普通模式多了分组编号, #1 #2 #3

![[Pasted image 20221125073625.png]]

提取数据、替换

var regex = /(\d&#123;4&#125;)-(\d&#123;2&#125;)-(\d&#123;2&#125;)/; 
var string = "2017-06-12"; 
console.log( string.match(regex) ); 
// => ["2017-06-12", "2017", "06", "12", index: 0, input: "2017-06-12"]

反向引用

可以在正则本身里引用分组,但只能引用之前出现的分组,即反向引用。
反向引用实际开发中因为对正则掌握不全面,很少使用,需要重视。

匹配 2022-11-25 字符,可以使用

var reg = \d&#123;4&#125;(-)\d&#123;2&#125;(-)\d&#123;2&#125;\

![[Pasted image 20221125075148.png]]

也可以使用反向引用。注意下面的正则中的 \1,是分组引用,后面第二个 - 就可以使用分组引用的 \ 去实现。

var reg = \d&#123;4&#125;(-)\d&#123;2&#125;\1\d&#123;2&#125;\

![[Pasted image 20221125074823.png]]

回溯

回溯和算法中的回溯非常像,都是先占有,然后等后面的匹配出现问题了,再回退,重新匹配。
正则 /ab{1,3}c/,匹配文本 abbbc,形式如下:
![[Pasted image 20221125080009.png]]
先匹配 3 个 b,然后匹配 c,这里一次性通过了,没有产生回溯。
如果匹配字符串 abbc, 那么将产生回溯
![[Pasted image 20221125080132.png]]
他会持续性的匹配 b 字符,知道出错,然后产生回退(回溯)。

回溯形式

贪婪量词

在局部是贪婪地,但是也要满足整体的正确匹配。

惰性量词

惰性量词就是在贪婪量词后面加个问号,表示尽可能少的匹配。

var string = "12345"; 
var regex = /(\d&#123;1,3&#125;?)(\d&#123;1,3&#125;)/; 
console.log( string.match(regex) ); 
// => ["1234", "1", "234", index: 0, input: "12345"]

![[Pasted image 20221125081204.png]]

惰性量词,匹配到第一次就结束,但是为了整体匹配达成,需要进行多次匹配。因此最后 {1,3}? 的匹配是 12

var string = "12345"; 
var regex = /(\d&#123;1,3&#125;?)(\d&#123;1,3&#125;$)/; 
console.log( string.match(regex) ); 
// => ['12345', '12', '345', index: 0, input: '12345', groups: undefined]

![[Pasted image 20221125081303.png]]

分支结构

分支结构也是惰性的,比如 /can|candy/,匹配字符串 candy,得到的结果是 can,前面的分支满足了,就不会尝试后面的匹配。

语言本身

语言结构

结构 说明
字面量 匹配一个具体字符,包括不用转义的和需要转义的。比如 a 匹配字符 “a”, 又比如 \n 匹配换行符,又比如 . 匹配小数点
字符组 匹配一个字符, 可以是多种可能之一, 比如 [0-9], 表示匹配一个数字。也有 \d 的简写形式。另外还有反义字符组,表示可以是除了特定字符之外任何一个字符,比如 [^0-9], 表示一个非数字字符,也有 \D 的简写形式
量词 表示一个字符连续出现, 比如 a{1, 3} 表示 “a” 字符连续出现 3 次。另外还有常见的简写形式, 比如 a+ 表示 “a” 字符连续出现至少一次
匹配一个位置,而不是字符。比如 ^ 匹配字符串的开头,又比如 \b 匹配单词边界, 又比如 (?=\d) 表示数字前面的位置
分组 用括号表示一个整体,比如 (ab)+,表示 “ab” 两个字符连续出现多次, 也可以使用非捕获分组 (?:ab)+。
分支 多个子表达式多选一, 比如 abc|bcd, 表达式匹配 “abc” 或者 “bcd” 字符子串。反向引用, 比如 \2, 表示引用第 2 个分组

操作符优先级

操作符描述 操作符 优先级
转义符 \ 1
括号和方括号 ()、(?:…)、(?=…)、(?!…)、[…] 2
量词限定符 {m}、{m, n}、{m,}、?、*、+ 3
位置和序列 ^、$、元字符、一般字符 4
管道符 | 5

晚上想发布的时候,好像还是很难记,送上打油诗一首:

尖尖是开头,美国有末日
加加叠叠叠,星星可多少
问号最神秘,最多给一次
括号分类型,分组还给你
中括号最花心,一个即是对
花括号最贪心,总想多又多
花括号加问号,才懂够用就好

配上字符之后即是:

尖尖 (^^) 是开头,美国 ( $$) 有末日
加加(++)叠叠叠,星星 (**) 可多可少
问号 (??) 最神秘,最多给一次
括号 () 分类型,物以群分
中括号 [] 最花心,一个即是对
花括号 {m,n} 最贪心,总想多又多
花括号配问号{m,n}?,才懂够用够用就好

参考

  1. 正则指引
  2. JavaScript 正则表达式迷你书