前言
工作到现在,一直没有好好看过正则表达式,正好最近在啃高程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