最近為了對html文件進行源碼處理,需要進行正則查找並替換。於是借着這個機會把正則系統地學一下,雖然以前也用過正則,但每次都是臨時學一下混過關的。在學習的過程中還是遇到不少問題的,特別是零寬斷言(這里還要吐槽下,網上到處都是都復制粘貼的內容,遇到個問題查看了不少重復的東西,汗!!!),所以在這里把自己的理解寫下來,方便以后查閱!
零寬度正預測先行斷言是什么呢,看msdn上的官方解釋定義
(?= 子表達式)
(零寬度正預測先行斷言。)僅當子表達式在此位置的右側匹配時才繼續匹配。例如,\w+(?=\d) 與后跟數字的單詞匹配,而不與該數字匹配。
經典的例子:某單詞以ing結尾,要獲取ing前面的內容
var reg = new Regex(@"\w+(?=ing)"); var str = "muing"; Console.WriteLine(reg.Match(str).Value);//返回mu
以上是網上到處可見的例子,到這里或許你明白了,原來就是返回了exp表達式前面的內容。
再看下面的的代碼
var reg = new Regex(@"a(?=b)c"); var str = "abc"; Console.WriteLine(reg.IsMatch(str));//返回false
為什么會返回false?
其實msdn官方定義已經說了,只是它說得很官方而已。這里需要我們注意一個關鍵點:此位置。沒錯,是位置而不是字符。那么結合官方定義和第一個例子來理解第二個例子:
因為a后面是b,則此時返回了匹配內容a(由第一個例子知道,只返回a不返回exp匹配的內容),此時a(?=b)c中的a(?=b)部分已經解決了,接下來要解決c的匹配問題了,此時匹配c要從字符串abc哪里開始呢,結合官方定義,就知道是從子表達的位置向右開始的,那么就是從b的位置開始,但b又不匹配a(?=b)c剩余部分的c,所以abc就不匹配a(?=b)c了。
那么如果要上面的進行匹配,正則應該如何寫呢?
答案是:a(?=b)bc
當然,有人會說直接abc就匹配上了,還要這么折騰嗎?當然不用這么折騰,只是為了說明零寬度正預測先行斷言到底是怎么一回事?關於其它的零寬斷言也是同一原理!