当前位置:网站首页>js正则-梳理
js正则-梳理
2022-06-21 09:50:00 【南风number】
一、创建方式
- 字面量:正则表达式直接放在/ /之中:
const rex = /pattern/;
- 构造函数:RegExp 对象表示正则表达式的一个实例:
const rex = new RegExp("pattern");
这两种方法的一大区别是对象的构造函数允许传递带引号的表达式,通过这种方式就可以动态创建正则表达式。
通过这两种方法创建出来的 Regex 对象都具有相同的方法和属性:
let RegExp1 = /a|b/
let RegExp2 = new RegExp('a|b')
console.log(RegExp1) // 输出结果:/a|b/
console.log(RegExp2) // 输出结果:/a|b/
二、模式匹配
1. 字符集合
如果我们想匹配 bat、cat 和 fat 这种类型的字符串该怎么办?可以通过使用字符集合来做到这一点,用 [] 表示,它会匹配包含的任意一个字符。这里就可以使用/[bcf]at/ig:
2. 字符范围
如果我们想要在字符串中匹配所有以 at 结尾的单词,最直接的方式是使用字符集,并在其中提供所有的字母。对于这种在一个范围中的字符, 就可以直接定义字符范围,用-表示。它用来匹配指定范围内的任意字符。这里就可以使用/[a-z]at/ig:
常见的使用范围的方式如下:
- 部分范围:[a-f],匹配 a 到 f 的任意字符;
- 小写范围:[a-z],匹配 a 到 z 的任意字符;
- 大写范围:[A-Z],匹配 A 到 Z 的任意字符;
- 数字范围:[0-9],匹配 0 到 9 的任意字符;
- 符号范围:[#$%&@];
- 混合范围:[a-zA-Z0-9],匹配所有数字、大小写字母中的任意字符。
3. 数量字符
如果想要匹配三个字母的单词,根据上面我们学到的字符范围,可以这样来写:
[a-z][a-z][a-z]
这里我们匹配的三个字母的单词,那如果想要匹配10个、20个字母的单词呢?难道要一个个来写范围吗?有一种更好的方法就是使用花括号{}来表示,来看例子:
可以看到,这里我们匹配到了所有连续5个字母的单词(包括超过5个字母的单词,不过只会匹配到前5个字母)。
其实匹配重复字符的完整语法是这样的:{m,n},它会匹配前面一个字符至少 m 次至多 n 次重复,{m}表示匹配 m 次,{m,}表示至少 m 次。
所以,当我们给5后面加上逗号时,就表示至少匹配五次:
所以这里就匹配到了所有连续5个或5个以上的单词。
当匹配次数为至少4次,至多5次时,匹配结果如下:
除了可以使用大括号来匹配一定数量的字符,还有三个相关的模式:
- +:匹配前面一个表达式一次或者多次,相当于 {1,};
- *:匹配前面一个表达式0次或者多次,相当于 {0,};
- ?:单独使用匹配前面一个表达式零次或者一次,相当于 {0,1},如果跟在量词*、+、?、{}后面的时候将会使量词变为非贪婪模式(尽量匹配少的字符),默认是使用贪婪模式。
来看一个简单的例子,这里我们匹配的正则表达式为/a+/ig,结果如下:
它和/a{1,}/ig的匹配结果是一样的:
使用/[a-z]+/ig就可以匹配任意长度的纯字母单词:
4. 元字符
使用元字符可以编写更紧凑的正则表达式模式。常见的元字符如下:
- \d:相当于[0-9],匹配任意数字;
- \D:相当于[^0-9];
- \w:相当于[0-9a-zA-Z],匹配任意数字、大小写字母和下划线;
- \W:相当于:[^0-9a-zA-Z];
- \s:相当于[\t\v\n\r\f],匹配任意空白符,包括空格,水平制表符\t,垂直制表符\v,换行符\n,回车符\r,换页符\f;
- \S:相当于[^\t\v\n\r\f],表示非空白符。
来看一个简单的例子:
这里使用\d来匹配任意数字、字母和下划线。这里就匹配到了7个连续四位的字符。
5. 特殊字符
使用特殊字符可以编写更高级的模式表达式,常见的特殊字符如下:
- .:匹配除了换行符之外的任何单个字符;
- \:将下一个字符标记为特殊字符、或原义字符、或向后引用、或八进制转义符;
- |:逻辑或操作符;
- [^]:取非,匹配未包含的任意字符。
来看一个简单的例子,如果我们使用 /ab*/ig 进行匹配,结果就如下:
那我们就是想要匹配 * 怎么办?就可以使用 \ 对其进行转义:
这样就只会匹配到 ab* 了。
或匹配也很简单,来看例子,匹配规则为:/ab|cd/ig,匹配结果如下:
这里就会匹配到字符串中所有 ab 和 cd 字符。那如果想要匹配 sabz 或者scdz呢?开头和结尾是相同的,只有中间的两个字符是可选的。其实只需要给中间的或部分加上括号就可以了:
取非规则在范围中使用,来看例子:
这里匹配到了所有非字母的字符。
6. 位置匹配
如果我们想匹配字符串中以某些字符结尾的单词,以某些字符开头的单词该如何实现呢?正则表达式中提供了方法通过位置来匹配字符:
- \b:匹配一个单词边界,也就是指单词和空格间的位置;
- \B:匹配非单词边界;
- ^:匹配开头,在多行匹配中匹配行开头;
- $:匹配结尾,在多行匹配中匹配行结尾;
- (?=p):匹配 p 前面的位置;
- (?!=p):匹配不是 p 前面的位置。
最常见的就是匹配开始和结束位置。先来看一个开始位置的匹配,这里使用 /^ex/igm 来匹配多行中以ex 开头的行:
使用/e$/igm来匹配以 e 结尾的行:
可以使用 \w+$ 来匹配每一行的最后一个单词:
需要注意,这里我们都使用 m 修饰符开启了多行模式。
使用 /(?=the)/ig 来匹配字符串中the前的面的位置:
我们可以使用\b来匹配单词的边界,匹配的结果如下:
这可能比较难理解,我们可以使用以下正则表达式来匹配完整的单词:\b\w+\b,匹配结果如下:
三、修饰符
正则表达式常见的修饰符如下:
- g:表示全局模式,即运用于所有字符串;
- i:表示不区分大小写,即匹配时忽略字符串的大小写;
- m:表示多行模式,强制 $ 和 ^ 分别匹配每个换行符。
这些修饰符总是用在最后一个正斜杠后面,可以一起使用。下面来分别看看这些修饰符的作用。
最开始的例子中,字符串中有两个“处”,但是只匹配到了一个。这是因为正则表达式默认匹配第一个符合条件的字符。如果想要匹配所有符合条件的字符,就可以使用 g 修饰符:
/处/g
这样就匹配到了所有符合条件的字符:
当需要匹配引英文字符串,并且忽略字符串的字母大小写时,i 修饰符就派上用场了。
/a/gi

还有一个小疑问, 如果是对象构造函数的方式来构造正则表达式使,如何添加这些修饰符呢?其实很简单,只要将修饰符作为第二个参数传递给 构造函数就可以了:
let regExp = new RegExp('[2b|^2b]', 'gi')
console.log(regExp) // 输出结果:/[2b|^2b]/gi
四、RegExp 实例
1. 实例方法
RegExp 实例置了test()和exec() 这两个方法来校验正则表达式。下面来分别看一下这两个方法。
(1)test()
test()用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。
const regex1 = /a/ig;
const regex2 = /hello/ig;
const str = "Action speak louder than words";
console.log(regex1.test(str)); // true
console.log(regex2.test(str)); // false
(2)exec()
exec()用于检索字符串中的正则表达式的匹配。该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。
const regex1 = /a/ig;
const regex2 = /hello/ig;
const str = "Action speak louder than words";
console.log(regex1.exec(str)); // ['A', index: 0, input: 'Action speak louder than words', groups: undefined]
console.log(regex2.exec(str)); // null
在当在全局正则表达式中使用 exec 时,每隔一次就会返回null,如图:
这是怎么回事呢?MDN 的解释如下:
为了解决这个问题,我们可以在运行每个exec命令之前将lastIndex赋值为 0:
2. 实例属性
RegExp实例还内置了一些属性,这些属性可以获知一个正则表达式的各方面的信息,但是用处不大。
| 属性 | 描述 |
|---|---|
| global | 布尔值,表示是否设置了g标志 |
| ignoreCase | 布尔值,表示是否设置了i标志 |
| lastIndex | 整数,表示开始搜索下一个匹配项的字符位置,从0算起 |
| multiline | 布尔值,表示是否设置了m标志 |
| source | 正则表达式的字符串表示,按照字面量形式而非传入构造函数重大的字符串模式匹配 |
五、字符串方法
在 JavaScript 中有6种常用的方法是支持正则表达式的,下面来分别看看这些方法。
1. search()
search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置。如果没有找到任何匹配的子串,则返回 -1。
const regex1 = /a/ig;
const regex2 = /p/ig;
const regex3 = /m/ig;
const str = "Action speak louder than words";
console.log(str.search(regex1)); // 输出结果:0
console.log(str.search(regex2)); // 输出结果:8
console.log(str.search(regex3)); // 输出结果:-1
可以看到,search() 方法只会返回匹配到的第一个字符的索引值,当没有匹配到相应的值时,就会返回-1。
2. match()
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。如果没有找到任何匹配的文本, match() 将返回 null。否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。
const regex1 = /a/ig;
const regex2 = /a/i;
const regex3 = /m/ig;
const str = "Action speak louder than words";
console.log(str.match(regex1)); // 输出结果:['A', 'a', 'a']
console.log(str.match(regex2)); // 输出结果:['A', index: 0, input: 'Action speak louder than words', groups: undefined]
console.log(str.match(regex3)); // 输出结果:null
可以看到,当没有 g 修饰符时,就只能在字符串中执行一次匹配,如果想要匹配所有符合条件的值,就需要添加 g 修饰符。
3. matchAll()
matchAll() 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。因为返回的是遍历器,所以通常使用for…of循环取出。
for (const match of 'abcabc'.matchAll(/a/g)) {
console.log(match)
}
//["a", index: 0, input: "abcabc", groups: undefined]
//["a", index: 3, input: "abcabc", groups: undefined]
需要注意,该方法的第一个参数是一个正则表达式对象,如果传的参数不是一个正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个 RegExp 。另外,RegExp必须是设置了全局模式g的形式,否则会抛出异常 TypeError。
4. replace()
replace() 用于在字符串中用一些字符串替换另一些字符串,或替换一个与正则表达式匹配的子串。
const regex = /A/g;
const str = "Action speak louder than words";
console.log(str.replace(regex, 'a')); // 输出结果:action speak louder than words
可以看到,第一个参数中的正则表达式匹配到了字符串的第一个大写的 A,并将其替换为了第二个参数中的小写的 a。
5. replaceAll()
replaceAll() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串,该函数会替换所有匹配到的子字符串。
const regex = /a/g;
const str = "Action speak louder than words";
console.log(str.replaceAll(regex, 'A')); // 输出结果:Action speAk louder thAn words
需要注意,当使用一个 regex 时,您必须设置全局(“g”)标志, 否则,它将引发 TypeError:“必须使用全局 RegExp 调用 replaceAll”。
6. split()
split() 方法用于把一个字符串分割成字符串数组。其第一个参数是一个字符串或正则表达式,从该参数指定的地方分割字符串。
const regex = / /gi;
const str = "Action speak louder than words";
console.log(str.split(regex)); // 输出结果:['Action', 'speak', 'louder', 'than', 'words']
这里的 regex 用来匹配空字符串,所以最终在字符串的每个空格处将字符串拆成了数组。
六、实际应用
1. 匹配密码
检查密码的格式,其包含至少一个大写字母、小写字母、数字、符号,长度为8-12位:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*\W).{8,12}$/g
这里我们主要使用了正则表达式中的正向前瞻,正向前瞻语法为(?=pattern),即在目标字符串的相应位置必须有pattern部分匹配的内容,但不作为匹配结果处理,更不会存储在缓冲区内供以后使用。来看一下这个正则表达式的每一部分的含义:
- (?=.*[a-z]):匹配任何后面跟着小写字母的字符;
- (?=.*[A-Z]):匹配任何后面跟着大写字母的字符;
- (?=.*\d):匹配任何后面跟着数字的字符;
- (?=.*\W):匹配任何后面跟着符号的字符;
- .{8,12}:匹配的长度至少为 8 个字符,至多为12个字符。
^和$可以保证匹配从字符串的开头到结尾进行匹配,也就是只对整个密码进行匹配,不考虑部分匹配。
下面是测试结果:
2. 匹配邮箱
检查电子邮箱的地址:
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-][email protected][a-zA-Z0-9-]+(?:\.[ a-zA-Z0-9-]+)*$/g
下面来看一下这个正则表达式每一部分的含义:
- [a-zA-Z0-9.!#$%&'*+/=?_~-]+:检查是否使用了所有有效字符并且至少有了一个(末尾的+`用于检查是否至少有一个字符);
- [a-zA-Z0-9-]+:这一部分用来检验主机名是否有效,主机名可以是大小写字母、数字、中横线。最后的 + 表示至少有一位;
- (?:.[a-zA-Z0-9-]+)*:这一部分是可选的域名后缀,这里使用的 * 就表示前面的字符是0个或者多个,这样.com、.com.cn等域名都可以匹配到;
- ^和$可以保证匹配从字符串的开头到结尾进行匹配,也就是只对整个邮箱字符串进行匹配,不考虑部分匹配。
下面是测试结果:
3. 匹配数字
检查数字是否是整数:/^\d+$/,其中\d+表示至少有一位数字。测试结果如下
检查数字是否是小数:/^\d*.\d+$/,其中\d* 表示至少有0位数字,.就是把小数点进行了转义操作,\d+就表示至少有一位小数位。测试结果如下:
校验一个数字是不是一个金额:/^\d+(.\d{2})?$/
七、在线正则网站
https://regex101.com/在线正则
https://regexr.com/在线正则
https://www.regexpal.com/在线正则
https://regex-vis.com/在线正则
vscode插件 Regex previewer

边栏推荐
- Three key directories in R language and their corresponding priorities: R_ Home directory, user directory, current working directory, files read by R's startup process
- How to convert mindspire model to onnx format and use onnxruntime reasoning - development test
- POI implements operation to generate word tables and operate chart data in word
- R language list data object, create list data object, index list data with [[], list data practice
- TC software outline design document (mobile group control)
- It is only seven days since the commencement of construction in 2022. I left the outsourcing company
- How to be an interesting person
- Ali has been working for 8 years. This learning note is left when he reaches P8. He has helped his friends get 10 offers
- Ccs7.3 how to erase only part of the flash sector when burning DSP on-chip flash (two projects of on-chip flash burning of a DSP chip)
- DSP gossip: how to save the compiled variables on the chip when the variables are defined in the code
猜你喜欢

Introduction and template of segment tree Foundation (I)

Solve the problem of error when typescript object gets value

Full stack development

Coordinate system transformation, application in inertial navigation antenna

DSP gossip: how to save the compiled variables on the chip when the variables are defined in the code

应用配置管理,基础原理分析

Classification of ram and ROM storage media

基因型填充前的质控条件简介

【实战】STM32MP157开发教程之FreeRTOS系统篇6:FreeRTOS 列表和列表项

stm32mp1 Cortex M4开发篇9:扩展板空气温湿度传感器控制
随机推荐
应用配置管理,基础原理分析
领导:谁再用redis过期监听实现关闭订单,立马滚蛋!
Signal power spectrum estimation
R language uses the < - operator to create a new variable, uses the existing data column (sum, mean) to create a new data column, uses the ifelse function or conditional judgment to create a discrete
About Alipay - my savings plan - interest rate calculation instructions
Concurrency - condition variable
121. Redux detailed summary + effect drawing + Case
[practice] stm32mp157 development tutorial FreeRTOS system 3: FreeRTOS counting semaphore
【云驻共创】企业数字化加速“新智造”
嵌入式远程岗位、兼职、接单、众包平台
The spring recruitment is also terrible. Ali asked at the beginning of the interview: how to design a high concurrency system? I just split
给电脑加装固态
Ali has been working for 8 years. This learning note is left when he reaches P8. He has helped his friends get 10 offers
R language sets na Rm=true parameter, deleting missing values in calculation and analysis to obtain valid calculation results (excluding missing values from analyses)
Original code, inverse code, complement calculation function applet; C code implementation;
Les nouveaux programmeurs optimisent une ligne de code lundi et sont exhortés à se retirer mercredi?
113. summary of common usage of moment.js
Stm32mp1 cortex M4 development part 8: LED lamp control experiment of expansion board
Vscode high-speed download address -- solve the problem of slow vscode Download
JS resource disaster recovery