一、前言
1.1 正则表达式用途
- 编译器中的词法分析器,使用正则表达式匹配代码中的关键字
- 网页上的表单,用正则表达式校验
- 爬虫,使用正则表达式提取需要的信息
1.2 工具网站
- 正则测试: regex101.com
- 正则练习:www.codejiaonang.com
二、基础
基础部分内容在于快速上手正则的基础使用
2.1 限定符
限定符用途:限制字符出现的个数
下面以限制hello后边感叹号的个数举例
问号:?
表示问号之前的字符可有可无(0或1个)
const reg = /hello!? world/
reg.test('hello world') // true
reg.test('hello! world') // true
reg.test('hello!! world') // false
星号:*
表示星号之前的字符可有可无(0或多个)
const reg = /hello!* world/
reg.test('hello world') // true
reg.test('hello! world!') // true
reg.test('hello!! world') // true
加号:+
表示加号之前的字符至少有一个(1或多个)
const reg = /hello!+ world/
reg.test('hello world') // false
reg.test('hello! world!') // true
reg.test('hello!! world') // true
大括号:{}
表示大括号之前的字符出现次数由大括号内限制
// 只能出现两次
const reg1 = /hello!{2} world/
reg1.test('hello! world!') // false
reg1.test('hello!! world!') // true
reg1.test('hello!!! world') // false
// 只能出现2到4次
const reg2 = /hello!{2,4} world/
reg2.test('hello!! world!') // true
reg2.test('hello!!! world') // true
reg2.test('hello!!!!!! world') // false
// 只能出现2到无限次
const reg3 = /hello!{2,} world/
reg3.test('hello!!!!!! world') // true
限定多个字符
使用小括号包裹多个字符
比如至少要出现一次"非常"
:
const reg = /我(非常)+爱你/
reg.test('我爱你') // false
reg.test('我非常爱你') // true
reg.test('我非常非常爱你') // true
2.2 或运算
竖线
|
表示或运算,使用时用小括号包裹
const reg = /我(真的|非常)爱你/
reg.test('我真的爱你') // true
reg.test('我非常爱你') // true
reg.test('我真的非常爱你') // false
2.3 字符组
匹配字符组中的任意内容一次,字符组使用中括号包裹(表示这个位置的字符,只能取自于中括号内)
比如匹配"Hello"
或"hello"
,第一个字母只能是"h"
或"H"
:
const reg = /[Hh]ello/
reg.test('Hello') // true
reg.test('hello') // true
字符组本身是匹配一个字符,结合限定符来变化字符个数:
const reg = /[Hh]{2}ello/
reg.test('hello') // false
reg.test('hhello') // true
reg.test('Hhello') // true
字符范围
可以在字符组中指定范围:
[a-z]
:所有小写字母[A-Z]
: 所有大写字母[0-9]
:所有数字[a-zA-Z0-9]
: 所有英文字母和数字
const reg = /[a-z0-9]/
reg.test('A') // false
reg.test('a') // true
reg.test('3') // true
字符组取反
在字符组最前加尖号(^
)表示匹配除了该字符组以外的所有字符
const reg = /[^a-z0-9]/
reg.test('A') // true
reg.test('a') // false
reg.test('3') // fasle
内置字符组
正则中预制了一些表示常见的字符组,通常以反斜杠(\
)开头:
用于表示常见的字符组,通常以反斜杠(\
)开头:
\d
:数字\w
:英文,数字,下划线\s
:空白符(空格,换行)
大写时一般表示取反:
\D
:非数字\W
:非英文,数字,下划线\S
:非空白符
句号
句号(.
)表示任意字符(不包含换行符):
const reg = /.好/
reg.test('你好') // true
reg.test('我好') // true
reg.test('你坏') // false
2.4 行首与行尾
^
:行首$
:行尾
匹配以"a"
开头,以"b"
结尾,中间任意两个字符:
const reg = /^a.{2}b$/
reg.test('ab') // false
reg.test('a12b') // true
reg.test('a12c') // false
2.5 转义符
匹配在正则中有特殊含义的字符时,要在前面加反斜杠\
。
比如需要匹配句号("."
)本身:
/abc./.test('abcd') // true,没有匹配到句号也通过,因为句号代表任意字符
/abc\./.test('abcd') // false, 转义后只能匹配字符串"abc."
/abc\./.test('abc.') // true
2.6 修饰符
修饰符位于正则最尾部,可以组合使用
/xxx/gi // 最后面的g和i就是两个修饰符
- g: 全局模式,正则默认匹配到第一个符合的字符就结束,g修饰符表示匹配到字符串结束。
- i:忽略大小写
2.7 贪婪匹配与懒惰匹配
正则表达式默认为贪婪匹配:在给定的范围内尽可能多的匹配字符
比如匹配这个字符串:"我喜欢玩(原神)和(星穹铁道)!!!"
期望得到:
"(原神)"
和"(星穹铁道)"
const str = '我喜欢玩(原神)和(星穹铁道)!!!'
str.match(/\(.+\)/g) // ['(原神)和(星穹铁道)']
但匹配到的结果是:
"(原神)和(星穹铁道)"
这就是贪婪匹配,因为括号中间的条件是任意数量字符,所以在匹配前后括号时,尽可能多的覆盖了括号中间的字符。
切换为懒惰匹配:在加号后面加一个问号:
const str = '我喜欢玩(原神)和(星穹铁道)!!!'
str.match(/\(.+?\)/g) // ['(原神)', '(星穹铁道)']
三、进阶
进阶部分目的在于了解正则的一些原理性概念和进阶使用