以前大三學習《編譯原理》的時候老師講了點叫斷言的東西,可是這門課壓根就沒聽懂過,因此一直找不到有價值的東西,好吧原諒我懶惰無知,理論不適合我,我只適合搬磚。許久以後一些關於正則的黑科技才發現正則裏也有較斷言的東東,好吧得了解了解這是什麼。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))/
匹配到的位置就是12
與345678
之間的位置,加了g
表全局匹配,
因此繼續匹配到知足條件的345
與678
之間的位置,在這些加,
就有了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(",","")
。
上面舉的一些例子可能不足以說明問題,若是你是精通正則的高手望勿噴,固然多多指教那就更好了。