正則位置匹配之簡單運用

寫在前面

本文僅對我遇到的一個關於字元串匹配替換的問題所了解到的正則運用做小小的分析記錄。不詳細介紹正則相關知識。如果想了解下正則位置匹配相關的內容,實名推薦老姚出品的 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-/"

結尾

文章雖短,權當記錄。如有謬誤,請大神指正輕拍。

後面會更多針對遇到的某個問題寫下分析記錄。