動態

詳情 返回 返回

什麼?前瞻斷言和後瞻斷言居然可以這麼牛? - 動態 詳情

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 grewer 頭像 haoqidewukong 頭像 zaotalk 頭像 linlinma 頭像 qingzhan 頭像 razyliang 頭像 leexiaohui1997 頭像 inslog 頭像 anchen_5c17815319fb5 頭像 banana_god 頭像 huichangkudelingdai 頭像 u_17443142 頭像
點贊 173 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.