正则表达式-入门篇

802 阅读9分钟

前言

工作到现在,一直没有好好看过正则表达式,正好最近在啃高程4,刷到正则表达式这一章,决心把正则好好的过一遍。下面是我在学习正则表达式的过程中记录的笔记。一开始看的时候还是有些无从下手,后来去看MDN的文档,也略觉得枯燥。最后的最后,在B站上搜到了胶囊大人正则表达式30分钟入门40分钟进阶不是托,发自内心的墙裂推荐),发现了编程胶囊这个网站,跟着他的步骤边学边写,结合MDN文档,瞬间感觉理解上清晰很多。后续还会更新进阶以及正则表达式属性及实例方法的笔记。


文章内容如有错误,欢迎各位大佬纠正!

入门表达式

[] 字符组

允许匹配一组可能出现的字符

匹配多个单词

使用字符组匹配RubyRuberubyrube

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

🌰: image.png

这里我们可以看到 \bmaster\b 就仅匹配有边界的master单词

边界?

首先我们看一下javascript是怎么解释断词的

JavaScript的正则表达式引擎将特定的字符集定义为“字”字符。不在该集合中的任何字符都被认为是一个断词。这组字符相当有限:它只包括大写和小写的罗马字母,十进制数字和下划线字符。

也就是说,\W匹配的字符都可以被理解为断词

以上面master举例,m到与mr到与r)相连的断词之间的这一段就可以理解为边界,边界的长度为0,它是一个比较抽象的存在

\B

上面关于\b的理解如果清晰了,那么\B其实就很好理解了,我自己的理解方法就是把所有的断词换成\w就可以了

看一个🌰: image.png

^ $ 开始和结束

正则表达是中,^指定的是一个字符串的开始,$指定的是一个字符串的结束

🌰:

指定字符串的开始 image.png

指定字符串的结束 image.png

. 任意字符

.字符代表匹配任何单个字符,它只能出现在方括号外

需要注意的是.字符只有一个不能匹配的字符,也就是换行符\n

看一个简单的🌰: image.png

? 可选字符

有时,我们可能想要匹配一个单词的不同写法,比如colorcolour,或者honorhonour

这个时候我们可以使用 ? 符号指定一个字符、字符组或其他基本单元可选,这意味着正则表达式引擎将会期望该字符出现零次或一次

🌰: image.png

通过这个案例我们可以知道?的作用就是匹配它之前的字符0次或1

可选任意字符

🌰: image.png

匹配多个数据

{N} 重复

在一个字符组后加上{N},就可以表示在它之前的字符组出线N

🌰:匹配xxx-xxxxx格式的电话号码

image.png

🌰🌰:

假设手机号码规则如下:

  • 必须是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

image.png

{M,} 开闭区间

有的时候,我们可能遇到字符组的重复区间是没有边界的

🌰:
image.png

闭区间不写即可表示匹配一个或无数个,我自己喜欢理解成至少匹配一个字符

速写

正则表达式提供了两个速写字符来表示常见的重复情况

速写方式描述
+匹配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

测试工具

RegExr