javascript正則斷言的理解

以前大三學習《編譯原理》的時候老師講了點叫斷言的東西,可是這門課壓根就沒聽懂過,因此一直找不到有價值的東西,好吧原諒我懶惰無知,理論不適合我,我只適合搬磚。許久以後一些關於正則的黑科技才發現正則裏也有較斷言的東東,好吧得了解了解這是什麼。javascript

那麼正則裏的斷言是什麼?

引用一段來自百科的說明java

用於查找在某些內容(但並不包括這些內容)以前或以後的東西,也就是說它們像b,^,$那樣用於指定一個位置,這個位置應該知足必定的條件(即斷言),所以它們也被稱爲零寬斷言。(來自百度百科)正則表達式

斷言在一些教材裏也稱做環視c#

斷言寫法

  • 前瞻斷言瀏覽器

    • (?=exp) 順序確定環視,表示所在位置右側可以匹配exp網絡

    • (?!exp) 順序否認環視,表示所在位置右側不能匹配exp學習

  • 後瞻斷言測試

    • (?<=exp) 逆序確定環視,表示所在位置左側可以匹配expcode

    • (?<!exp) 逆序否認環視,表示所在位置左側不能匹配expip

解析:
前瞻斷言(從當前位置向前測試)和後瞻斷言(從當前位置向後測試)。

具體的例子看使用方法吧。

注:

  • 括號是必須的,寫法:(?!=...)

  • 有些語言並不徹底支持,好比:javascript的正則並不支持後瞻斷言表達式,使用了會報錯的。

  • 其中exp是一個正則表達式能夠是子模式,如:(?=((exp))

  • 環視也稱斷言;斷言是不佔用字符串的((?=exp)因此不能引用,exp是佔用字符串的)

使用方法

  • (?=exp) 順序確定環視,表示所在位置右側可以匹配exp

來個javascript的例子,匹配.gif的文件名

var s="img.jpg,abc.gif,123.jpeg";
s.match(/\w*(?=\.gif)/);

結果:["abc"]

/\w*(?=\.gif)/中的\w*表示能夠有零個或多個字符,匹配到的是abc,那麼(?=.gif)這個匹配到什麼?其實他匹配到的只是一個位置,這就是斷言的初衷,匹配到的是介於abc.gif的位置。
好吧不信來驗證下:
去掉正則表達式的\w*,在匹配到的內容替換成#

var s="img.jpg,abc.gif,123.jpeg";
s.replace(/(?=\.gif)/,"#");

結果:"img.jpg,abc#.gif,123.jpeg"

回到定義:(?=exp)順序確定環視,表示所在位置右側可以匹配exp;那麼/\w*(?=\.gif)/的意思就是以.gif做爲右邊的位置才匹配成功,那就會匹配到abc.gif這裏就成功了,以前說過斷言匹配不佔用字符寬度(即不結果不會包含斷言部分),因此匹配到的字符串就是\w*即'abc'。

  • (?!exp) 順序否認環視,表示所在位置右側不能匹配exp

例子:匹配非.gif的文件名

var s="img.jpg,abc.gif,123.jpeg";
s.match(/(\w*)(?:\.)(?!gif)\w*/g);

結果:["img.jpg", "123.jpeg"]

/(\w*)(?:\.)(?!gif)\w*/g這個正則表示(\w*)(?:\.)的右邊不是gif匹配成功。

對於後瞻斷言的例子這裏不舉例子,若是哪位有空填下吧。

使用例子

來看一個來自網絡的問答例子:把一串數10000000000字以,分隔成10,000,000,000

這個例子0有點多看着耀眼,先從簡單的開始;好吧咱們換一串字符串好比:12345678轉換成12,345,678

正則怎麼實現呢?
看代碼:

var s="12345678";
s.replace(/(?=(\d{3})+(?!\d))/g,",");

是的就這樣就能夠了。
好吧,來分析下原理:

/(?=(\d{3})+(?!\d))/g,其中(\d{3})+表示前面的三個數字串至少出現一組,然後接(?!\d)則表示的是數字的右邊不是數字,
那麼就是結尾,那/(?=(\d{3})+(?!\d))/匹配到的位置就是12345678之間的位置,加了g表全局匹配,
因此繼續匹配到知足條件的345678之間的位置,在這些加,就有了12,345,678了。

若是想看這個例子的過程能夠改寫下代碼:

var s="12345678";
s.replace(/(?=((\d{3})+)(?!\d))/g,function(){console.log(arguments);return ","});

結果:
循環1: ["", "345678", "678", 2, "12345678"]
循環2: ["", "678", "678", 5, "12345678"]
返回值:"12,345,678"

好吧,原理再也不細說,本身複製代碼到瀏覽器控制檯執行看效果。

那麼這個10000000000轉成10,000,000,000就很簡單了。

可是若是數字串的位數是3的倍數會出如今數字串前面也有一個,號,好吧再正則去掉result.replace(",","")

後語

上面舉的一些例子可能不足以說明問題,若是你是精通正則的高手望勿噴,固然多多指教那就更好了。

相關文章
相關標籤/搜索