正則表達之零寬斷言(零寬度正預測先行斷言)


http://www.cnblogs.com/mu-mu/archive/2013/02/06/2893581.html

 

  最近為了對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就匹配上了,還要這么折騰嗎?當然不用這么折騰,只是為了說明零寬度正預測先行斷言到底是怎么一回事?關於其它的零寬斷言也是同一原理!

 

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

(?= 子表達式)

(零寬度正預測先行斷言。) 僅當子表達式在此位置的右側匹配時才繼續匹配。例如,\w+(?=\d) 與后跟數字的單詞匹配,而不與該數字匹配。此構造不會回溯。

(?<= 子表達式)

(零寬度正回顧后發斷言。) 僅當子表達式在此位置的左側匹配時才繼續匹配。例如,(?<=19)99 與跟在 19 后面的 99 的實例匹配。此構造不會回溯。

 

    
http://deerchao.net/tutorials/regex/regex.htm
(?<= # 斷言要匹配的文本的前綴 <(\w+)> # 查找尖括號括起來的字母或數字(即HTML/XML標簽) ) # 前綴結束 .* # 匹配任意文本 (?= # 斷言要匹配的文本的后綴 <\/\1> # 查找尖括號括起來的內容:前面是一個"/",后面是先前捕獲的標簽 ) # 后綴結束

 

下面講下我的理解

(1).零寬度

這表示匹配是一個位置(Loaction)而不是子表達式。

(2).預測先行,回顧后發

(?= 子表達式),預測先行, 返回與子表達式匹配的前面位置,從做左到右匹配。

(?<= 子表達式),回顧后發,返回與子表達式匹配的后邊位置,從右到左匹配。

我們可以想象有在模式匹配過程中有一指針標志當前匹配的位置,這樣當子表達式匹配時 預測先行 把指針指到子表達式前邊,回顧后發則為后邊。可以參考上邊代碼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM