正则表达式总结

正则表达式总结

正则作用

  • 给定的字符串是否符合正则表达式的过滤逻辑 (匹配)
  • 可以通过正则表达式,从字符串中获取我们想要的特定部分 (提取)
  • 强大的字符串替换能力(替换)

正则概述

正则表达式(Regular Expression)是用于描述一组字符串特征的模式,用来匹配特定的字符串。通过特殊字符+普通字符来进行模式描述,从而达到文本匹配目的工具。因此正则表达式是用于匹配字符串中字符组合的模式。

编写正则表达式

正则创建方式

  • 字面量创建

1
2
// 两个斜杠之间包起来的,都是用来描述规则的元字符(不可添加变量)
const reg = /\d+/
  • 构造函数创建

1
2
3
// 有两个参数:元字符字符串,修饰符字符串,元字符中间可以添加变量
const reg = new RegExp('\\d+'+ value + '\\d+' , 'g')

两种创建方式的区别

1
2
3
// 构造函数因为传递的是字符串,\需要写两个才代表斜杠
let reg1 = /\d+/g
let reg2 = new RegExp('\\d+','g')
  • 两个 / 中间包起来的都是元字符
1
2
3
4
5
6
// 如果正则中要包含某个变量的值,则不能使用字面量方式创建
let str = 'gzy'
let reg = /^@"+str+"@$/
reg.test('@gzy@') // false
reg.test('@""strrr"@') // true

  • 有需要变量的需求只能用构造函数创建
1
2
3
let str = 'gzy'
let reg = new RegExp('^@"+str+"@$')
reg.test('@gzy@')

正则表达式语法

  • 普通字符 abc 中国 123 等
  • 特殊字符(元字符、限定符、中括号):正则表达式中有特殊意义的字符

元字符

元字符就是在正则表达式中具有

特殊含义

的字符

元字符 说明
\d 匹配数字
\D 匹配非数字
\w 匹配字母数字下划线_
\W 匹配非字母、数字、下划线_
\s 匹配空白符(空格)
\S 匹配非空白符
. 匹配任意除了换行符(回车键)之外的单个字符

限定符

限定符就是控制字符出现的次数,对字符个数限制

限定符 说明
n* 匹配任何包含零个或者多个n的字符串。n{0,}
n+ 匹配任何包含至少一个n的字符串。n{1,}
n? 匹配任何包含零个一个n的字符串。{0,1}
n{x} 匹配包含x个n的序列的字符串。
n{x,} 匹配包含至少x个n的序列的字符串。
n{x,y} 匹配包含至少x个至多y个n的序列的字符串。
n$ 匹配任何结尾为n的字符串。
^n 匹配任何开头为n的字符串。
  • 正则表达式使用时,会对字符串整体校验,完全符合才能够匹配。否则不匹配。
  • 针对花括号中次数限制,在去匹配字符串时,首先是从前先后匹配,先按照至多次数匹配,若至多不符合要求,则再按照较少的匹配。
  • 针对花括号中次数限制至少是0时,此时若字符串中没有匹配的项是符合要求的,若字符串中的字符不匹配也是符合要求的。

中括号

一个中括号就代表一个字符串,中括号的目的解视控制一个字符的范围。

中括号 说明
[abc] 查找一个括号之间的任何字符。
abc 查找一个任何不在方括号之间的字符,^在中括号中有取反的意思。
[0-9] 查找一个任何从0至9的数字。
[a-z] 查找一个任何从小写a到小写z的字符。
[A-Z] 查找一个任何从大写A到大写Z的字符。
[A-z] 查找一个字母(包含大小写和下划线)。
[[\u4e00-\u9fa5]] 查找一个汉字。

或模式

特殊符号:正则1|正则2, 或者。 符合或两边其中一个就可以匹配。

如:google,baidu,bing; // 匹配三种其中一种字符串

正则:google|baidu|bing

分组模式

特殊符号: (正则) ;

组指的是一个小集体,分组就是将一个大集体可以分成几个小集体。

如:控制你的名字连续出现的次数,最少1次,最多3次

正则:^(bruce){1,3}$

修饰符

修饰符 全称 说明
i ignoreCase 忽略单词大小写匹配
m multiline 可以进行多行匹配
g global 全局匹配

相关方法

正则常用方法

方法 描述 返回
test 检查字符串中是否含有检测的字符 boolean
exec 寻找字符串中是否含有检测的字符 将找到的字符串按数组返回
  • test

1
/str/.test('hello world');  //要求字符串包含string,所以返回false
  • exec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var reg=/ab/g;
var str="abababab";
reg.lastIndex //0
reg.exec(str)//["ab",index:0,input:"abababab"]
reg.lastIndex//2
reg.exec(str)//["ab",index:2,input:"abababab"]
reg.lastIndex//4
reg.exec(str)//["ab",index:4,input:"abababab"]
reg.lastIndex//6
reg.exec(str)//["ab",index:6,input:"abababab"]
reg.lastIndex//8
reg.exec(str)//null
reg.lastIndex//0
reg.exec(str)//["ab",index:0,input:"abababab"]

//reg.lastIndex是可手动修改的
reg.lastIndex=0; // reg.lastIndex重置0
reg.exec(str)
// ["ab",index:0,input:"abababab"],与上面结果中的index相同

// 若匹配规则不含有global属性,那在允许exec()方法后lastIndex值始终为0
var reg=/ab/;
var str="abababab";
reg.lastIndex // 0
reg.exec(str) // ["ab",index:0,input:"abababab"]
reg.lastIndex // 0
reg.exec(str) // ["ab",index:0,input:"abababab"]

字符串常用方法

方法 描述
search 检索与正则表达式相匹配的值,返回匹配字符串的位置,匹配不到时返回 -1
match 找到一个或多个正则表达式的匹配,在规则中是否含义global属性时返回匹配数组
replace 替换为正则表达式匹配的字符串
split 把字符串按照正则分为字符串数组
  • search

1
"hello world".search(/w/) // 6
  • match

1
2
3
4
5
const str = "hello world";
const reg1 = /o/;
str.match(reg1); // ['o', index: 4, input: 'hello world', groups: undefined]
const reg2 = /o/g;
str.match(reg2); // ['o', 'o']
  • replace

1
"hello world".replace(/world/g,"baidu"); // hello baidu
  • split

1
2
3
4
5
var str="a1b2c";
var reg=/\d/g;
str.split(reg); // ["a","b","c"],即将分隔符两侧的字符串进行拆分
var reg=/(\d)/g; // "()"代表记录反向引用,将匹配表达式也返回回来
str.split(reg); // ["a","1","b","2","c"]

捕获组与非捕获组

正则表达式分组分为捕获组(Capturing Groups)与非捕获组Non-Capturing Groups。正则里面是用成对的小括号来表示分组的,如(\d)表示一个分组,(\d)(\d)表示有两个分组,(\d)(\d)(\d)表示有三个分组,有几对小括号元字符组成,就表示有几个分组。

  • 分组的目的

    • 作为可选分支
    • 简写重复模式
    • 缓存捕获数据及反向引用(只有捕获组才可以被反向引用)
  • 捕获组

1
/(\w)+/.test('hello world') //(\w)组成一个捕获组
  • 非捕获组
1
/(?:\w)+/.test('hello world') //(?:\w)组成一个非捕获组
不需要用到分组里面的内容的时候,用非捕获组,主要是为了提升效率,因为捕获组多了一步保存数据的步骤,所以一般会多耗费一些时间。 - 命名捕获组 捕获组其实是分为编号捕获组Numbered Caputuring Groups和命名捕获组Named Capturing Groups的,我们上面说的捕获组,默认指的是编号捕获组。命名捕获组,也是捕获组,只是语法不一样。命名捕获组的语法如下:(?group) 或 (?'name'group),其中 name 表示捕获组的名称,group 表示捕获组里面的正则。
1
2
3
4
5
6
7
8
9
10
const str = '2022-12-15';
const reg = /(\d{4})-(\d{2})-(\d{2})/;
str.match(reg)
// ['2022-12-15', '2022', '12', '15', index: 0, input: '2022-12-15', groups: undefined]
const isNotCaputuringReg = /(?:\d{4})-(?:\d{2})-(?:\d{2})/;
str.match(isNotCaputuringReg)
// ['2022-12-15', index: 0, input: '2022-12-15', groups: undefined]
const namedCaputuringReg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
str.match(namedCaputuringReg)

命名捕获组

贪婪匹配与非贪婪匹配

贪婪匹配即照着”量词”规则中要求的更多个的情况去做匹配。

非贪婪匹配,在”量词”规则后边多加一个问号”?”。

“量词”包括 ?、*、+、{}、{n,}、{n,m}

1
2
3
4
5
6
var str="aaaaa";
var reg=/a+/g;
str.match(reg);//["aaaaa"]
var reg=/a??/g;//第一个问号代表0~1个,第二个问号代表能取0就不取1去做匹配
str.match(reg);//["","","","","",""]

问号在正则中的五大作用

  • 问号左边是非量词元字符:本身代表量词元字符,出现零到一次
  • 问号左边是量词元字符:取消捕获时候的贪婪性
  • (?:)只匹配不捕获
  • (?=)正向预查
  • (?!)负向预查

反向引用

反向引用就是正则中’ \1 ‘用法,下列代码中(\w)首先匹配a,’\1’引用a,后面量词’+’表示出现一次获多次。

1
2
3
4
var str = 'aaaaabbbbbbcccccccd'
var reg = /(\w)\1+/g
str.replace(reg,'$1') // $1是第一个小括号中的内容
// abc

参考文章/手册

就因为这三个知识点,我彻底学废了”正则表达式“
知道这 20 个正则表达式,能让你少写 1,000 行代码
JS正则表达式完整教程(略长)
聊聊让人头疼的正则表达式
百度工程师带你玩转正则