正则表达式速成

122 阅读4分钟

一、前言

1.1 正则表达式用途

  1. 编译器中的词法分析器,使用正则表达式匹配代码中的关键字
  2. 网页上的表单,用正则表达式校验
  3. 爬虫,使用正则表达式提取需要的信息

1.2 工具网站

  1. 正则测试: regex101.com
  2. 正则练习: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) // ['(原神)', '(星穹铁道)']

三、进阶

进阶部分目的在于了解正则的一些原理性概念和进阶使用