快速掌握正则表达式 | 04 元字符真好玩

Posted 一百个Chocolate

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速掌握正则表达式 | 04 元字符真好玩相关的知识,希望对你有一定的参考价值。

在上一篇我们介绍了一些好玩的元字符,真是好玩,也没想到阅读量还是挺多的,也算是鸽了一段时间,今天我们继续来玩玩元字符,真好玩!

到底匹配多少个字符

上一篇文章中,我们了解到了数字与非数字匹配、字母数字与非字母数字的匹配,以及后面提及的空白字符与非空白字符,然后进制的匹配问题。

那么,我们看看下面的例子:

let arr = ['https://yangchaoyi.vip/','Chocolate'];
let reg = /\\w\\w\\w\\w\\w:\\/\\/\\w\\w\\w\\w\\w\\w\\w\\w\\w\\w\\.\\w\\w\\w\\//g;
let res = arr.filter(item=>item.match(reg));
console.log(res); // ['https://yangchaoyi.vip/']

我们想要匹配一个网址,然后写下了如上述所示的正则表达式,看完之后有何感受?

还学个屁!

日常开个玩笑哈,既然说是这个元字符好玩,那么本次一定带来一些解放方案咯。

解决痛点

匹配一个或多个字符

在上文中,我们的痛点应该很清楚了,那就是多次、重复问题。

那么,我们现在来介绍 + 这个符号,在正则表达式中,它可以匹配一个或多个字符,直接上例子吧:

let arr = ['https://yangchaoyi.vip/','Chocolate'];
let reg = /\\w+:\\/\\/\\w+\\.\\w+\\//g;
let res = arr.filter(item=>item.match(reg));
console.log(res); // ['https://yangchaoyi.vip/']

ohhhhh,代码少了许多,是不是简单了不少呢。

当然,还有其它的匹配操作。

匹配零个或多个字符

直接再看一波例子吧:

let arr = ['https://yangchaoyi.vip/','Chocolate'];
let reg = /\\w*:\\/\\/[\\w\\.]*\\//g;
let res = arr.filter(item=>item.match(reg));
console.log(res); // ['https://yangchaoyi.vip/']

在这个例子中的不同点是:[\\w\\.]*

这个意思是对于 [a-zA-Z0-9_]. 我们构造了一个字符集合,在字符集合后面有一个 *,就代表这匹配零歌或多个字符,注意字符集和里面我们进行了转义,即\\.,在这里的话,[\\w\\.] 的实际效果和[\\w.] 实际效果一样,但是转义一下会好一点,因为 . 可以匹配任意字符,所以用来匹配 . 看起来没多少区别。

不过像 . 这样的元字符如果呗包在字符集集合里面使用的时候,会被解释为普通字符,无需转义,因此其实写不写无所谓,但是为了自己清楚以及别人看得更懂,写一下会更好。

匹配零个或一个字符

接下来再来介绍相关的元字符 ?,它的作用在之前两个介绍之后应该显而易见了,直接看例子:

let arr = ['https://yangchaoyi.vip/','http://yangchaoyi.vip/','Chocolate'];
let reg = /\\w+s?:[\\w]?/g;
let res = arr.filter(item=>item.match(reg));
console.log(res); // ['https://yangchaoyi.vip/', 'http://yangchaoyi.vip/']

在这个例子中,我将 ? 放在 s 之后,想表达的意思是相匹配网址,不管是 http 的还是 https 的都可以,于是通过 ? 操作,匹配零次以及一次。

给定区间范围的匹配

在上文中,我们要么是匹配一个以上,或者起码要匹配一个,又或是匹配零个或一个。

我们发现这个范围是从 0 到 无穷大的,假设我们就想要某个区间范围的呢?

直接看例子吧:

let arr = ['#1','#22','#33','#4444','#55555','#666666','Chocolate'];
let reg = /#[\\w]6/g;
let res = arr.filter(item=>item.match(reg));
console.log(res); // ['#666666']

从上述例子来看,我们可以通过 来设定一个重复次数,可以是单个数值,当然也可以是区间,比如:

let arr = ['#1','#22','#3ab'];
let reg = /#\\d2,3/g;
let res = arr.filter(item=>item.match(reg));
console.log(res); // ['#22']

范围与无穷大

上述,我们设定了一个区间,但有时候我们右区间可能没有设定值,默认应该为无穷大,又应该是怎样呢?

直接看如下例子:

let arr = ['#1','#22','#33abc', '123123123123', '#123321'];
let reg = /#\\d2,/g;
let res = arr.filter(item=>item.match(reg));
console.log(res); // ['#22', '#33abc', '#123321']

这样,我们的区间范围变成了 [2, 无穷大]。

遇到一个问题

上述来看,我们都还是比较轻松的,掌握了一些匹配操作,但也只是解决了一些基础问题,我们来看下面这个例子:

let str = '<div>001</div><p>中间的文字</p><div>002</div>';
let reg = /<div>.*<\\/div>/g;
let res = str.match(reg);
console.log(res); // ['<div>001</div><p>中间的文字</p><div>002</div>']

诶,发现不对了乜有,我想匹配出两个的呢,为啥只有一个结果?

过度匹配

我们发现这里出现了过度匹配问题,其原因还是元字符这一块,因为像 * 和 + 我们之前介绍他们的区间右侧其实是无穷大的,属于是一种【贪婪型】的元字符,所以会一直匹配下去,找到最右边的 </div>

这显然不是我们本例想要的一个结果,不过我们在本例可以这样稍作修改:

let str = '<div>001</div><p>中间的文字</p><div>002</div>';
let reg = /<div>\\d*<\\/div>/g;
let res = str.match(reg);
console.log(res); // ['<div>001</div>', '<div>002</div>']

也还是可以匹配到两个结果,不过这并没有解决我们的问题。

贪婪—懒惰

对于【贪婪型】的元字符,相对的我们应该也会有【懒惰型】的,其实用法非常简单,就是加一个 ? 即可,我们直接上例子吧:

let str = '<div>001</div><p>中间的文字</p><div>002</div>';
let reg = /<div>\\d*?<\\/div>/g;
let res = str.match(reg);
console.log(res); // ['<div>001</div>', '<div>002</div>']

仅仅和之前相比多加了一个 ? 就解决了过度匹配问题,这样就不会因为过于贪婪匹配过多我们不想要的内容了,在实际应用中也许会遇到这两种情况,合理的使用他们会有不错的效果哦。

小结

不知不觉已经坚持输出第四篇博客了,中间还是停了一大段时间,继续努力更新完整个系列~

本小节内容到底就结束啦,感谢各位的阅读,我们期待下一篇吧。

以上是关于快速掌握正则表达式 | 04 元字符真好玩的主要内容,如果未能解决你的问题,请参考以下文章

快速掌握正则表达式 | 04 元字符真好玩

快速掌握正则表达式 | 03 元字符真好玩

快速掌握正则表达式 | 03 元字符真好玩

快速掌握正则表达式 | 02 掌握进阶的匹配操作

快速掌握正则表达式 | 02 掌握进阶的匹配操作

快速掌握正则表达式 | 01 掌握最基本的匹配