博客 / 詳情

返回

什麼?前瞻斷言和後瞻斷言居然可以這麼牛?

JavaScript 中的前瞻斷言(lookahead)和後瞻斷言(lookbehind)相信用過的小夥伴就知道它的威力了,在一些特定的需求場景下,可以做到四兩撥千斤的作用,今天讓我們來盤點一下在 JavaScript 正則表達式中這兩個秘密武器吧。

前瞻斷言和後瞻斷言,在其他語言的正則表達式中也存在,這個特性不是 JavaScript 的專屬

概念定義

不管是前瞻斷言還是後瞻斷言,最終目的都是尋找在指定的模式(pattern)下,這個指定模式(pattern)前面或者後面的字符子串, 得到的結果永遠是這些 前面或者後面的字符子串 而不是這個指定的模式(pattern)本身

前瞻或後瞻在匹配的時候不會實際匹配和捕獲字符,只是檢查某個位置前後是否符合指定條件,並不會改變正則的 lastIndex,在檢查完之後,正則表達式的其他部分繼續進行匹配。

前瞻斷言

在中文互聯網上 lookahead 被翻譯成 前瞻斷言、先行斷言等

前瞻斷言,是用於在檢查後面的子串是否匹配某個模式, 前瞻斷言包括正向前瞻負向前瞻斷言

  • 正向前瞻X(?=pattern),如果 X 後面的子串符合 pattern模式, 就匹配 X。
  • 負向前瞻X(?!pattern), 如果 X 後面的子串不符合 pattern模式, 就匹配 X。

後瞻斷言

在中文互聯網上 lookahead 被翻譯成 後瞻斷言、後行斷言等

後瞻斷言,是用於在檢查前面的子串是否匹配某個模式, 後瞻斷言包括正向後瞻斷言負向後瞻斷言

  • 正向後瞻(?<=pattern)X,匹配 X 前面滿足pattern 的子串。
  • 負向後瞻(?<!pattern)X,匹配 X 前面不滿足 pattern 的子串。

這裏有點需要注意的是 前瞻斷言是檢查後面的子串是否匹配,後瞻斷言是檢查前面的子串是否匹配。

這個規則感覺就是主打一個叛逆....

直接上代碼

前瞻斷言

  • 正向前瞻

利用正向前瞻實現金額字符串格式化為帶有千分位分隔符的格式。 例如 12345, 轉化為 12,345

圖片

圖片

解釋一下上述的正則表達式:

  • \B:匹配非單詞邊界。確保逗號不會被添加在開頭
  • (?=(\d{3})+(?!\d)):匹配符合右側有一個或多個三位數字,且這些三位數字不是字符串的結尾。
這個正則同時使用了正向前瞻和負向前瞻。剛開始可能比較繞,可以看看下面的可視化原理慢慢消化一下

圖片

通過上述正則匹配到的結果,再使用 replace 方法用來替換為逗號, 即可實現金額的千分位

  • 負向前瞻

我們可以用負向前瞻來過濾一些不符合條件的字符子串。例如下面我們需要匹配出不是金額的數字。

圖片

圖片

/\d+\b(?!元)/g 正則語法的意思是 “搜索 字符中的數字,但前提是後面沒有 這個字符”。

圖片

\b 是用於匹配一個單詞的邊界。這裏使用 \b 就是為了匹配完整的數字。不然上面的測試用例裏面的 15 中 的數字 1 也符合屬於數字,而且1後面也沒有跟 這個字符

單詞邊界指的是在單詞字符(字母、數字或下劃線)和非單詞字符(如空格、標點符號或其他字符)之間的位置,同時字符串的開頭或結尾也存在單詞的邊界。

後瞻斷言

  • 正向後瞻

正向後瞻是如果當前匹配項前面有特定的匹配子串的話,當前匹配項就會被匹配,否則就跳過。

圖片

圖片

這裏匹配 $ 後面的金額, 我們可以用正向後瞻斷言去匹配出來。只有這個數字前面的內容滿足 $ 就會匹配上,並返回到最終的結果中去。

圖片

  • 負向後瞻

如果你剛看完上面的正向後瞻的示例代碼,此時你想在上面的基礎上,只匹配金額前面只有一個$ 的, 這時候我們就可以用負向後瞻去做進一步約束。

這裏使用 負向後瞻並不是最優解,這裏只是為了做代碼演示構造的場景。

圖片

圖片

圖片

可以從可視化正則裏面看出,負向後瞻就是隻要當前匹配項前面不是 $$`的時候,才進行匹配,所以 `$$34 就會被忽略掉

不過為了應用這個例子,我這裏是故意這樣處理的,實際上為了滿足只匹配一個 $ 的金額數字的話,我們可以直接在上面的 正則加上 \s 即可, 即: /(?<=\s\$)\d+/g

兼容性

前瞻斷言的兼容性是最好的,基本上是全綠的狀態,直接無腦衝就行了。

圖片

當我查caniuse 的時候,有被震驚到,第一次遇到這種兼容性這麼好特性。要是前端所有的標準屬性有這兼容性就好了,好了,有點扯遠了哈。

後瞻斷言的兼容性差一些,除了在 Safari 瀏覽器中兼容性稍微差點,其他的都支持度很不錯。

圖片

小結

相信通過上面的介紹,你已經掌握了使用 前瞻斷言和後瞻斷言的精髓了,相信我使用它可以讓你寫正則的速度嗖嗖的,下班早早的。

如果這篇文章對你有幫助,歡迎點贊👍、關注➕、轉發 ✔ !

user avatar lanlanjintianhenhappy 頭像 guizimo 頭像 tigerandflower 頭像 hightopo 頭像 coderleo 頭像 flymon 頭像 shaochuancs 頭像 buxia97 頭像 jianqiangdepaobuxie 頭像 yilezhiming 頭像 liyl1993 頭像 lesini 頭像
138 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.