Revan1i

vuePress-theme-reco revan1i    2019 - 2020
Revan1i Revan1i

Choose mode

  • dark
  • auto
  • light
Home
TimeLine
Category
  • javascript
  • css
  • react
  • js
  • how
  • math
  • regexp
  • algorithm
  • feeling
Tag
Contact
  • GitHub
author-avatar

revan1i

25

文章

20

标签

Home
TimeLine
Category
  • javascript
  • css
  • react
  • js
  • how
  • math
  • regexp
  • algorithm
  • feeling
Tag
Contact
  • GitHub

JavaScript正则表达式参考手册

vuePress-theme-reco revan1i    2019 - 2020

JavaScript正则表达式参考手册


revan1i 2017-09-03 22:10:32 javascript regexp

"cover"

# 概述

正则表达式(regular expression)是一个描述字符模式的对象,有点像字符串的模板,可以对文本进行强大的模式匹配和文本检索与替换功能。 新建正则表达式有两种方式。一种是使用字面量,以斜杠表示开始和结束。

var regex = /java/;
1

另一种是使用RegExp构造函数

var regex = new RegExp('java');
1

这两种方法都是等价的。下面介绍正则表达式的匹配规则

# 匹配规则

# 元字符

大部分字符在正则表达式中,就是字面的含义,比如/java/匹配java, 除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思。正则表达式严格区分大小写,这些字符叫做“元字符”,主要有以下几个:

元字符 描述
. 匹配除换行符以外的任意字符
\d 匹配数字,相当于字符组[0-9]
\w 匹配字母, 数字, 下划线
\s 匹配任意的空白符(包括制表符,空格,换行等)
\b 匹配单词开始或结束的位置
^ 匹配行首
$ 匹配行尾

# 点字符

点字符(.)匹配除回车(\r)、换行(\n)、行分隔符(\u2028)和段分隔符(\u2029)以外的字符

/a.c/
1

上面代码中a.c匹配a和c之间包含任意一个字符的情况,只要是这三个字符在同一行即可,可以匹配abc但不匹配abbc四个字符的情况。

# 选择符

选择符(|)表示'or'的选择关系,选择符会包括它前后的多个字符,比如/ab|cd/匹配ab或者cd,而不是b或者c

# 反义元字符

元字符 描述
\D 匹配非数字的任意字符,等价于[^0-9]
\W 匹配除字母,数字,下划线以外的任意字符
\S 匹配非空白的任意字符
\B 匹配非单词开始或结束的位置
[^x] 匹配除x以外的任意字符

# 重复限定符

假设重复次数为n

|限定符|描述|记忆方式| |:----------😐:-----------😐 |*|n>=0|看看天上的星星,可能一颗没有,可能零散有几颗,可能数也数不过来。| |+|n>=1|加号是追加的意思,得先有一个,然后才考虑追加。| |?|n=0 or n=1|问号的意思表示,有吗?| |{x}|n=x|| |{x,}|n>=x|| |{x,y}|x<=n<=y||

# 贪婪模式和非贪婪模式

默认情况下,上一节的限定词都是贪婪模式,即尽可能最大可能的匹配,即匹配直到下一个字符不满足匹配规则为止。

var str = 'aaa'
str.match(/a+/)   // aaa  贪婪模式
str.match(/a+?/)  // a 非贪婪模式
1
2
3

上面代码,默认是贪婪模式,会一直匹配到字符a没有为止,所以会匹配到3个a. 如果在限定词后增加?,则是非贪婪模式,表示尽可能少的去捕获字符

# 字符类

可供选择的字符放在方括号[]内,表示匹配其中一个字符。比如:[xyz]匹配字符x, y或z,如果中括号中包含元字符,则元字符不在具有元字符的功能,比如[+.?]匹配加号,点号或问号。 有两个字符在字符类中有特殊含义

# 脱字符(^)

[^xyz]表示除了xyz中的字符都可以匹配,如果方括号内没有其他字符,就表示匹配一切字符,其中包括换行符,而点号(.)是不包括换行符的,其中要注意的是脱字符只有在字符类的第一个位置才有特殊意义,否则就是字面含义

# 连字符(-)

对于连续序列的字符,连字符(-)可以提供简写形式,表示字符的连续范围。比如[a-z]表示26个小写字母,但是当连字符不出现在方括号内,就不具备简写的作用,只代表字面的含义。 不要过分使用连字符,设定一个很大的范围,否则很可能选中意料之外的字符。最典型的例子就是[A-z],表面上它是选中从大写的A到小写的z之间52个字母,但是由于在ASCII编码之中,大写字母与小写字母之间还有其他字符,结果就会出现意料之外的结果。

/[A-z]/.test('\\') // true
1

上面代码中,由于反斜杠(\)的ASCII码在大写字母与小写字母之间,结果会被选中。

# 分组

正则表达式中的小括号表示分组匹配

/(abc)+/.test('abcabc')  // true
1

分组可以方便的表示重复次数,还可以用于捕获,请看捕获性分组

# 捕获性分组

捕获性分组,通常由一对小括号加上子表达式组成,捕获分组所匹配的内容暂储存在内存中以便下次使用,捕获性分组会创建反向引用,每个反向引用都用一个编号或名称来标识,主要通过$+编号或者+编号表示法进行引用

var reg = 'abcabc'.match(/(.)b(.)/)
console.log(reg)   // ['abc', 'a', 'c']
console.log((RegExp.$1))    // a
console.log((RegExp.$2))    // c
1
2
3
4

上面代码中,正则表达式/(.)b(.)/使用了两个括号,第一个括号捕获a,第二个括号捕获c。 RegExp.指向该分组捕获的内容,+编号只能在正则表达式外使用。 注意,使用组匹配时,不宜同时使用g修饰符,否则match方法不会捕获分组的内容。

var reg = 'abcabc'.match(/(.)b(.)/g)   // ['abc', 'abc']
1

上面代码使用了带g修饰符的正则表达式,结果match方法只捕获了匹配整个表达式的部分

# 反向引用

获取捕获性分组所匹配结果的过程称为“反向引用”。在正则表达式内部,可以用\n引用括号匹配的内容,n是从1开始的自然数,表示对应顺序的括号。

/(.)b(.)\1b\2/.test('abcabc')   // true
1

上面代码中,\1表示第一个括号匹配的内容,\2表示第二个括号匹配的内容。括号也可以嵌套

/a((..)\2)\1/.test('adededede')  // true
1

上面代码中,\1指向外层括号,\2指向内层括号,按照从左到右左括号出现的顺序确定编号。

# 非捕获性分组

(?:x)称为非捕获性分组,表示不返回该组匹配的内容,即匹配的结果中不计入这个括号。 它的作用是在要使用括号的情况下,不会占用一个组匹配。比如需要匹配foo或者foofoo,正则表达式可写/(foo){1, 2}/,但是这样就占用了一个组匹配,写成/(?:foo){1, 2}/作用与前一个正则表达式一样,但是不会占用组匹配

var result = 'abc'.match(/(?:.)b(.)/) // ['abc', 'c']
1

上面代码中,第一个括号是非捕获性分组,所以最后返回的结果没有第一个括号的内容,只有第二个括号匹配的内容。

# 先行断言

先行断言的形式为x(?=y),x只有在y前面才匹配,y不会计入返回结果,括号内的部分不会返回到结果

var result = 'abc'.match(/b(?=c)/)   // ['b']
1

上面代码使用了先行断言,b在c前面所以被匹配,但是括号对应的c不会被返回

# 先行否定断言

先行否定断言的形式为x(?!y),x只有不在y前面才匹配,y不会计入返回结果

var result = 'abdbc'.match(/b(?!c)/)   // ['b]
1

上面代码使用了先行否定断言,b不在c前面所以被匹配,但是括号对应的c不会被返回

# 参考资料

[1] 阮一峰, JavaScript标准参考教程 [2] 路易斯, 正则表达式前端使用手册

# 附录

"regexp cheatsheep"