正则位置匹配之简单运用

写在前面

本文仅对我遇到的一个关于字符串匹配替换的问题所了解到的正则运用做小小的分析记录。不详细介绍正则相关知识。如果想了解下正则位置匹配相关的内容,实名推荐老姚出品的 https://zhuanlan.zhihu.com/p/27309508。

抛出问题

输入一个url,如果末尾没有/ 的话,需要自动加上。

function addSlash(url) {}    addSlash('y.qq.com/music'); // => "y.qq.com/music/"  addSlash('y.qq.com/music/'); // => "y.qq.com/music/"  addSlash('y.qq.com/music-'); // => "y.qq.com/music-/"  addSlash('y.qq.com/music-/'); // => "y.qq.com/music-/"

这个问题并不难,但感觉用 if 判断来解决不是太优雅,正则匹配才是正道。

正则表达式是匹配模式,要么匹配字符,要么匹配位置。—— 老姚

这里很明显是需要匹配位置,然后在匹配到的位置上加上 /

根据位置匹配的初步了解,写出:

function addSlash(url) {      // 匹配最后一个位置,这个位置前面不是 `/`      return url.replace(/(?!/)$/, '/');  }    addSlash('y.qq.com/music'); // => "y.qq.com/music/"  addSlash('y.qq.com/music/'); // => "y.qq.com/music//"  addSlash('y.qq.com/music-'); // => "y.qq.com/music-/"  addSlash('y.qq.com/music-/'); // => "y.qq.com/music-//"

为什么最后的位置还会被再补上一个 /

把$去掉,换上全局符号,看下会怎么匹配。

function addSlash(url) {      return url.replace(/(?!/)/g, '/');  }    addSlash('y.qq.com/'); // => "/y/./q/q/./c/o/m//"

对于位置的理解,我们可以理解成空字符""。 比如"hello"字符串等价于如下的形式: "hello" == "" + "h" + "" + "e" + "" + "l" + "" + "l" + "o" + "";

因此: y.qq.com/ 等价于 ()y().()q()q().()c()o()m()/() ,括号代表位置,每个字符中间以及开头、结尾都有个“位置”。

所以(?!/) 匹配的前面不是/的位置,也就是 (/)y(/).(/)q(/)q(/).(/)c(/)o(/)m()/(/)

很明显 ()/ 这个位置不会再加上 / ,但结尾的() ,因为这个位置后面什么都没有,也确实不是 / ,因此还会加上。

回到 /(?!/)$/ 这个正则,它匹配的是结尾的位置并且这个位置后面不是 / ,所以最后一个字符无论是不是 / ,都会被再补上一个 /

解决

上面的正则确实是匹配了结尾的位置,但问题在于是以“结尾的位置”作为判断条件。

如何以最后一个字符为条件,精准匹配上结尾位置?这里用ES6中的 negative lookbehind ?<!

即匹配的是一个位置,而这个位置前面不是 /

function addSlash(url) {      return url.replace(/(?<!/)$/, '/', '/');  }    addSlash('y.qq.com/music'); // => "y.qq.com/music/"  addSlash('y.qq.com/music/'); // => "y.qq.com/music/"  addSlash('y.qq.com/music-'); // => "y.qq.com/music-/"  addSlash('y.qq.com/music-/'); // => "y.qq.com/music-/"

结尾

文章虽短,权当记录。如有谬误,请大神指正轻拍。

后面会更多针对遇到的某个问题写下分析记录。