正则表达式用法,看完以后就不用去网上找啦

之前实习工作或者刷题的时候有时碰到需要用到正则表达式地方,都是在网上直接找的,昨天系统的学习了一下,在此做个记录以及用自己的方式讲出来,巩固一下,或许也能帮到你。
参考链接:https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md

首先正则表达式是用来匹配字符串的,在JS中封装有RegExp方法供我们使用,我们只需要编写匹配的规则,就能用来匹配或者对特定要求的字符串做出判断了。
例如可以搭配字符串的replace方法来将匹配到的字符串替换成想要的字符串,也可以用regexp.test(str)方法来判断字符串是否符合我们编写的正则表达式。

基本匹配

那么最基本的正则表达式就是一段直白的字符串咯,例如/test/,就会匹配字符串(this is the test)中的test。

元字符

但正则的精髓在于利用元字符来代替普通的字符,以此在冗长复杂的字符串中匹配到我们想要的内容。下表是一些元字符,他们都有着特殊的含义:

元字符 描述
. 句号匹配任意单个字符除了换行符。
* 匹配>=0个重复的在*号之前的字符。
+ 匹配>=1个重复的在*号之前的字符。
? 标记?之前的字符为可选。
[ ] 字符种类。匹配方括号内的任意字符。
[^ ] 否定的字符种类。匹配除了方括号里的任意字符
{num1, num2} 匹配num1<=x<=num2个花括号之前的字符或字符集。
( ) 字符集,匹配括号内所有字符
^ 从开始开始匹配(也就是必须以什么开头)
$ 从末尾开始匹配(以什么为结束)
| 或运算符,匹配符号前或后的字符
\ 转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \

那么有了这些元字符,我们就可以编写正则表达式了,例如编写一个匹配手机号码的表达式,必须以13、18、15开头的11位号码。

const reg = new RegExp(/^1[385][0-9]{9}$/)
const str1 = '13226154267'
const str2 = '14226154267'
console.log(reg.test(str1), reg.test(str2)) // true  false

上述例子使用到了^$[]{}这4个元字符,^$代表了字符串只能是特定格式的手机号,如果不是以手机号开头并且结尾的就不匹配,例如在手机号前面或者后面多加一位数字都不行,因为我们限定了长度。
1[385]代表了第一位一定是1,而第二位只能在385里面选择,那么前两位确定了,后面只剩下9位,所以继续给定0-9的字符集[0-9],并且限定匹配个数为9个{9},这样子一个符合题意的正则表达式就写出来了。
当然也不止这种写法,如果能理解上面的元字符,相信这种写法你也能快速理解:

const reg = new RegExp(/^1(3|8|5)[0-9]{9}$/)
或者
const reg = new RegExp(/^(13|18|15)[0-9]{9}$/)

简写字符集

可能这时你就发现上面写法有些冗余,因为一个数字需要写[0-9],那如果还要包含大小写字母或者一些符号,那匹配一个字符将会如下面一样很长:

const reg = new RegExp(/[0-9a-zA-Z_@]/)

所以接下来是要学一些简写字符集,如下表:

简写 描述
. 除换行符外的所有字符
\w 匹配所有字母数字,等同于 [a-zA-Z0-9_]
\W 匹配所有非字母数字,即符号,等同于: [^\w]
\d 匹配数字: [0-9]
\D 匹配非数字: [^\d]
\s 匹配所有空格字符,等同于: [\t\n\f\r\p{Z}]
\S 匹配所有非空格字符: [^\s]
\f 匹配一个换页符
\n 匹配一个换行符
\r 匹配一个回车符
\t 匹配一个制表符
\v 匹配一个垂直制表符
\p 匹配 CR/LF(等同于 \r\n),用来匹配 DOS 行终止符
\b 表示单词边界
\B 表示非单词边界,应理解为(非单词)边界,而不是非(单词边界),它仍然匹配的是边界

有了简写字符集我们也可以再优化下我们的表达式啦

const reg = new RegExp(/^1[385]\d{9}$/)

学到这里已经能解决大部分需要用到正则表达式的场景了,但还没完,因为上述我们匹配的都是针对需要匹配的部分(我在说什么),如果你想要匹配包含(或者不包含)有特定前缀或者后缀的字符串,但不想把这些前后缀包含在里面,就需要用到零宽度断言(前后预查)了。

零宽度断言(前后预查)

?=… 正先行断言
正先行断言,表示第一部分表达式之后必须跟着 ?=…定义的表达式。
?!.. 负先行断言
正先行断言,用于筛选所有匹配结果,筛选条件为 其后不跟随着断言中定义的格式。
听着可能有点懵,但我举个例子你就明白了。例如在一个字符串数组中,我需要匹配压缩包的文件名,那么压缩包的文件名格式是 由字母、数字和下滑线组成的名字(不能以数字开头),再加上后缀.tar、.rar、.zip。

const filename = ['demo', '1reg.zip', 're0.txt', 'study1.tar', 'setup.exe']
const reg = new RegExp(/^[a-zA-Z_]\w*(?=.(tar|rar|zip)$)/)
for(const name of filename) {
    
    
	console.log(reg.exec(name)) // 获取匹配的字符串
}
//null
//null
//null
//['study1', 'tar', index: 0, input: 'study1.tar', groups: undefined]0: "study1"1: "tar"groups: undefinedindex: 0input: "study1.tar"length: 2[[Prototype]]: Array(0)...]
//null

上面的例子就是使用了正先行断言,应该能理解了吧,那么负先行断言和下面的正后发断言和负后发断言也是同样的道理。另外值得注意的是,这些断言需要写在()里面。
?<= … 正后发断言
正后发断言 记作(?<=…) 用于筛选所有匹配结果,筛选条件为 其前跟随着断言中定义的格式。
?<!.. 负后发断言
负后发断言 记作 (?<!..) 用于筛选所有匹配结果,筛选条件为 其前不跟随着断言中定义的格式。
再来一个例子,例如我要筛选出中国大陆地区的手机号码,那么应该是+86开头的,但是我只取号码的主体部分,而不要前缀。知道了规则之后就可以用正则表达式来编写了。

const reg = new RegExp(/(?<=^\+86)1[385]\d{9}$/) //注意加号需要转义

标志

在上面所举的例子中,我们都是只验证一整个字符串是否是匹配的,那么如果我们要匹配字符串中所有符合正则表达式的字串呢?那就需要用到标志了,以下是几种正则表达式的标志,也是模式修正符:

标志 描述
i 忽略大小写。
g 全局搜索。
m 多行修饰符:锚点元字符 ^ $ 工作范围在每行的起始。

这个应该挺好理解的,我就不举例子了。

贪婪匹配与惰性匹配

正则表达式默认采用贪婪匹配模式,在该模式下意味着会匹配尽可能长的子串。我们可以使用 ? 将贪婪匹配模式转化为惰性匹配模式。

const str = 'The fat cat sat on the mat.'
const reg1 = new RegExp(/(.*at)/)
const reg2 = new RegExp(/(.*?at)/)
console.log(reg1.exec(str))
console.log(reg2.exec(str))
//['The fat cat sat on the mat', 'The fat cat sat on the mat', index: 0, input: 'The fat cat sat on the mat.', groups: undefined]
//['The fat', 'The fat', index: 0, input: 'The fat cat sat on the mat.', groups: undefined]

关于正则表达式的内容基本就差不多了,干看着好像挺容易的,但一上手可能就不知道怎么使用或者记不住了,主要还是得多练习!

猜你喜欢

转载自blog.csdn.net/weixin_45732455/article/details/129814975
今日推荐