正则表达式第三回--模式、分组与前瞻

贪婪的正则

正则是默认贪婪的,它会尽可能多的匹配,我想这是一个大家都知道的事实。 经典例子:

'12345678'.replace(/\d{3,7}/g, '#')

// 输出: #8

可以看到,规则是匹配3~7个数字,由于正则默认是贪婪模式,匹配了最大数量7个;

如果我们希望它尽可能少的匹配,也就是说一旦匹配成功就不继续匹配了,只需要在量词后面加个问号即可。

'12345678'.replace(/\d{3,7}?/g, '#')

// 输出: ##78

分组

我们知道,量词是作用于紧挨着它的那个元字符或原义文本字符或分组的

'a1b2c3d4'.replace(/[a-z]\d{3}/g, "#")

// 输出: a1b2c3d4

上面这个示例中,我们本来试图匹配一个小写英文字母加数字连续出现3次的场景,把它换成#,但是事与愿违,规则与字符串并没有匹配上。实际上,紧挨着量词{3}的是一个元字符\d,所以这里的意思是:匹配数字连续出现三次。

如果要准确匹配我们的初始想法,可以给这个组合加上分组,修改后如下:

'a1b2c3d4'.replace(/([a-z]\d){3}/g, "#")

// 输出: #d4

当然,分组的魅力不在这里,分组的最大魅力在于分组引用,在repalce函数的第二个参数中,可以直接在字符串

神奇的"或"

或的写法是|,正则的或是单竖杠,JS中逻辑符号的或是双竖杠,这点需要注意。

或符号|在没有碰到分组边界的时候会把正则表达式“切割”成好几段,在遇到分组边界时则停止,比如/Lady|Gaga/表示匹配单词LadyGaga

"LadyGaga".replace(/Lady|Gaga/g, '#');
// 输出: ##

注意:或字符两边不要留空格,写成/Lady | Gaga/这样,因为这里的空格也属于原义文本字符。

当然,一开始我们也提到了,在遇到分组边界符时,或字符就“割”不动了,会停下来。这种情况比较少。

有前瞻,没有后顾

所谓前瞻,就是当匹配到符合正则的内容时,向前检查前面的内容是否符合断言部分。

断言这个概念是什么意思呢?它可以在里面书写一切的正则表达式,形式为(?=我们写的正则规则),但和普通的正则表达式不同的是:它不算作正式规则的一部分,只作为一种我们定义规则的辅助规则。举个栗子就明白了:

"my love, my heart".replace(/my\slove/g, '#');
// 正常书写正则,输出为 #, my heart

"my love, my heart".replace(/my(?=\slove)/g, '#');
// 用断言书写后面的空格加love,输出 # love, my heart
// 断言内的空格加love并没有随my一起被替换掉

原来这特么就叫断言啊。

注意一下前瞻的方向,因为字符串的匹配是从左到右,所以向前,也就是向右。

posted @ 2020-03-20 12:00  陌上兮月  阅读(202)  评论(0编辑  收藏  举报