前言
工作到现在,一直没有好好看过正则表达式,正好最近在啃高程4,刷到正则表达式这一章,决心把正则好好的过一遍。下面是我在学习正则表达式的过程中记录的笔记。一开始看的时候还是有些无从下手,后来去看MDN的文档,也略觉得枯燥。最后的最后,在B站上搜到了胶囊大人
的正则表达式30分钟入门40分钟进阶(不是托
,发自内心的墙裂推荐),发现了编程胶囊
这个网站,跟着他的步骤边学边写,结合MDN文档,瞬间感觉理解上清晰很多。后续还会更新进阶
以及正则表达式属性及实例方法
的笔记。
文章内容如有错误,欢迎各位大佬纠正!
入门表达式
[]
字符组
允许匹配一组可能出现的字符
匹配多个单词
使用字符组匹配Ruby
、Rube
、ruby
、rube
let str = 'ruby, rube, Ruby, Rube';
let pattern = /[Rr]ub[ye]/g;
console.log(str.match(pattern));
// ['ruby', 'rube', 'Ruby', 'Rube']
区间
有一些常见的字符组非常大,例如我们要匹配任意的数字和字母,每次使用[0123456789]
,[abcdefghi...]
,这样属实是有些繁琐!
这个时候我们就可以用到区间,[0-9]
,[a-z]
,[A-Z]
let str = '娜娜和老王约好了在二月十四日前往SexGod酒店共度良宵,酒店的电话为012345678、987654321';
let pattern = /[a-zA-z0-9]+/g;
console.log(str.match(pattern));
// ['SexGod', '012345678', '987654321']
匹配目标数据
找出下列数据的规律,然后进行匹配
abc01
,ddd02
,afcf01
,acac11
,321
,acef33
,bbc000
我们发现这里出现了a,b,c,d,e,f,0,1,2,3
这些字符,由此可以得到两个区间[a-f]
,[0-3]
let str = 'abc01,ddd02,afcf01,acac11,321,acef33,bbc000';
let pattern = /[a-f0-3]+/g;
console.log(str.match(pattern));
// ['abc01', 'ddd02', 'afcf01', 'acac11', '321', 'acef33', 'bbc000']
\
匹配特殊字符
在上面的正则表达式中,我们用到了 -
号代表了区间,但是我们有时候需要匹配的符号就是 -
号,该怎么办呢?
这个时候我们就要对 -
号进行转义操作,即 \-
。下面看一个匹配特殊符号的🌰
匹配特殊符号
let str = '[],-------,()';
let pattern = /[\[\]\-()]+/g;
console.log(str.match(pattern));
// ['[]', '-------', '()']
[^...]
取反
到目前为止,我们定义的字符组都是由可能出现
的字符定义,不过有时候我们可能希望根据不会出现
的字符定义字符组,这是时候我们就可以用到取反
匹配 不包含数字 的字符组
let str = 'javascipt123node456vue666react888material98765';
let pattern = /[^0-9]+/g;
console.log(str.match(pattern));
// ['javascipt', 'node', 'vue', 'react', 'material']
匹配 爱 后面不包含 你 的数据
let strArr = ['爱吗', '爱哦', '爱我自己', '爱了', '我爱我', '我爱你', '爱你', '爱你爱你', '不爱你', '爱你一万年'];
let pattern = /爱[^你]/;
const result = [];
for (let i of strArr) {
if (pattern.test(i)) {
result.push(i)
}
}
console.log(result);
// ['爱吗', '爱哦', '爱我自己', '爱了', '我爱我']
匹配 不含小写字母 的数据
let strArr = ['01234', '1234567890', 'ABCDEFG', 'CODEJIAONANG123', '[]', '+_)(91283)', '-*/123566ABV','ab','abc','abcd','www','codejiaonang','com','pthonregext'];
let pattern = /[^a-z]+/;
const results = [];
for (let i of strArr) {
if (pattern.test(i)) {
results.push(i)
}
}
console.log(results);
// ['01234', '1234567890', 'ABCDEFG', 'CODEJIAONANG123', '[]', '+_)(91283)', '-*/123566ABV']
快捷方式
快捷匹配
正常我们匹配所有的字母,会使用[a-zA-Z]
,匹配数字会使用[0-9]
那么还有更简洁的方式吗?
正则表达式引擎提供了一些快捷方式:
快捷方式 | 描述 |
---|---|
\w | 匹配一个单字字符(字母、数字或者下划线) ,等价于 [A-Za-z0-9_] |
\W | 匹配一个非单字字符(字母、数字或者下划线) ,等价于 [^A-Za-z0-9_] |
\d | 匹配一个数字,等价于[0-9] |
\D | 匹配一个非数字字符,等价于[^0-9] |
\s | 匹配一个空白字符,包括空格、制表符、换页符和换行符 |
\S | 匹配一个非空白字符 |
\n | 匹配一个换行符(U+000A) |
\r | 匹配一个回车符(U+000D) |
这里列举一些常用的快捷匹配,更多内容请查阅正则表达式 - -JavaScript | MDN
\b
\B
单词边界和非单词边界
\b
🌰:
这里我们可以看到 \bmaster\b
就仅匹配有边界的master
单词
边界?
首先我们看一下javascript是怎么解释断词的
JavaScript的正则表达式引擎将特定的字符集定义为“字”字符。不在该集合中的任何字符都被认为是一个断词。这组字符相当有限:它只包括大写和小写的罗马字母,十进制数字和下划线字符。
也就是说,\W
匹配的字符都可以被理解为断词
以上面master
举例,m
到与m
(r
到与r
)相连的断词之间的这一段就可以理解为边界,边界的长度为0,它是一个比较抽象的存在
\B
上面关于\b
的理解如果清晰了,那么\B
其实就很好理解了,我自己的理解方法就是把所有的断词换成\w
就可以了
看一个🌰:
^
$
开始和结束
正则表达是中,^
指定的是一个字符串的开始,$指定的是一个字符串的结束
🌰:
指定字符串的开始
指定字符串的结束
.
任意字符
.
字符代表匹配任何单个字符,它只能出现在方括号外
需要注意的是:
.
字符只有一个不能匹配的字符,也就是换行符\n
看一个简单的🌰:
?
可选字符
有时,我们可能想要匹配一个单词的不同写法,比如color
和colour
,或者honor
与honour
。
这个时候我们可以使用 ?
符号指定一个字符、字符组或其他基本单元可选,这意味着正则表达式引擎将会期望该字符出现零次或一次。
🌰:
通过这个案例我们可以知道?
的作用就是匹配它之前的字符0
次或1
次
可选任意字符
🌰:
匹配多个数据
{N}
重复
在一个字符组后加上{N}
,就可以表示在它之前的字符组出线N
次
🌰:匹配xxx-xxxxx格式的电话号码
🌰🌰:
假设手机号码规则如下:
- 必须是
11
位的数字; - 第一位数字必须以
1
开头,第二位数字可以是[3,4,5,7,8]
中的任意一个,后面9
个数是[0-9]
中的任意一个数字
let strArr = [
'18111234589',
'18711001111',
'13713201111',
'13712345678',
'14712345897',
'15721565489',
'17721565489',
'29711001111',
'30711001111',
'41711001111',
'58-1110011110',
'68711001111',
'12345678911',
'200110023057123'
]
let pattern = /^1[34578]\d{9}/;
const result = [];
for (let i of strArr) {
if (pattern.test(i)) {
result.push(i)
}
}
console.log(result);
// ['18111234589', '18711001111', '13713201111', '13712345678', '14712345897', '15721565489', '17721565489']
{M,N}
重复区间
有些时候,我们并不知道具体要匹配字符组重复的次数,比如身份证又15
位也有18
位的
那么这个时候,重复区间就闪亮登场了,语法:{M,N}
,M
是下界,N
是上界
举个🌰:
使用正则表达式提取电话号码,假设电话号码有两种规则:
- 以
3
个数字开头,后面7
个数字,例如:020-7281333
- 以
4
个数字开头,后面7
个数字,例如:0731-8283431
{M,}
开闭区间
有的时候,我们可能遇到字符组的重复区间是没有边界的
🌰:
闭区间不写即可表示匹配一个或无数个,我自己喜欢理解成至少匹配一个字符
速写
正则表达式提供了两个速写字符来表示常见的重复情况
速写方式 | 描述 |
---|---|
+ | 匹配1 个到无数个,等价于{1,} |
* | 匹配0 个到无数个,等价于{0,} |
我们再来看一个匹配电话号码的🌰:
假设电话号码可以有下列两种方式:
- 0XX-XXXXXXX,例如
020-8810456
; - 0XXXXXXXXX,例如
0208810456
。
020
代表区号,8810456
是电话号码,区号第一个数字必须是0
,电话号码的第一个数字必须大于等于1。
let strArr = [
'010-7810456',
'020-8810456',
'030-1810456',
'0208810456',
'0107810456',
'0107811356',
'020-88104XX',
'01007214569',
'3208810456',
'010-08104560',
'010-0810456',
'120-8810456',
]
let pattern = /^0\d{2}-?[1-9]\d{6}/;
const result = [];
for (let i of strArr) {
if (pattern.test(i)) {
result.push(i)
}
}
console.log(result);
// ['010-7810456', '020-8810456', '030-1810456', '0208810456', '0107810456', '0107811356']
参考
编程胶囊-正则表达式入门
正则表达式 - javascript|MDN