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 瀏覽器中兼容性稍微差點,其他的都支持度很不錯。
小結
相信通過上面的介紹,你已經掌握了使用 前瞻斷言和後瞻斷言的精髓了,相信我使用它可以讓你寫正則的速度嗖嗖的,下班早早的。
如果這篇文章對你有幫助,歡迎點贊👍、關注➕、轉發 ✔ !