麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 編程 > Regex > 正文

正則表達(dá)式——詳細(xì)講解平衡組

2020-03-16 20:54:30
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

這篇文章適合你嗎?

要讀懂這篇文章的精髓,你最好要有一點(diǎn)正則匹配原理的基礎(chǔ)。比如".*?"匹配文本內(nèi)容"asp163",稍懂正則表達(dá)式的人都知道可以匹配,但是你知道他的匹配過(guò)程嗎?如果你不太清楚,那么下面的內(nèi)容,對(duì)你來(lái)說(shuō)可能不太適合,或許,看的太吃力且無(wú)法領(lǐng)悟平衡組的用法。因此,我建議你先了解正則表達(dá)式NFA引擎的匹配原理。想要整理一份易懂易描述的話,的確要費(fèi)些時(shí)間,但不知道這篇內(nèi)容會(huì)不會(huì)達(dá)到我預(yù)期的效果。慢慢完善吧~(注:這是我2010年寫的,現(xiàn)在拿過(guò)來(lái),有時(shí)間將自己做為讀者來(lái)看本篇文章,修改有問(wèn)題的地方,并增加些實(shí)例,盡量做到通俗易懂。)

一般正則教程中對(duì)平衡組的介紹

如果想要匹配可嵌套的層次性結(jié)構(gòu)的話,就得使用平衡組了。舉個(gè)例子吧,如何把“xx <aa <bbb> <bbb> aa> yy”這樣的字符串里,最長(zhǎng)的尖括號(hào)內(nèi)的內(nèi)容捕獲出來(lái)?

這里需要用到以下的語(yǔ)法構(gòu)造:
(?<group>) 把捕獲的內(nèi)容命名為group,并壓入堆棧
(?<-group>) 從堆棧上彈出最后壓入堆棧的名為group的捕獲內(nèi)容,如果堆棧本來(lái)為空,則本分組的匹配失敗
(?(group)yes|no) 如果堆棧上存在以名為group的捕獲內(nèi)容的話,繼續(xù)匹配yes部分的表達(dá)式,否則繼續(xù)匹配no部分
(?!) 順序否定環(huán)視,由于沒(méi)有后綴表達(dá)式,試圖匹配總是失敗

如果你不是一個(gè)程序員(或者你是一個(gè)對(duì)堆棧的概念不熟的程序員),你就這樣理解上面的三種語(yǔ)法吧:第一個(gè)就是在黑板上寫一個(gè)(或再寫一個(gè))"group",第二個(gè)就是從黑板上擦掉一個(gè)"group",第三個(gè)就是看黑板上寫的還有沒(méi)有"group",如果有就繼續(xù)匹配yes部分,否則就匹配no部分。
我們需要做的是每碰到了左括號(hào),就在黑板上寫一個(gè)"group",每碰到一個(gè)右括號(hào),就擦掉一個(gè),到了最后就看看黑板上還有沒(méi)有-如果有那就證明左括號(hào)比右括號(hào)多,那匹配就應(yīng)該失敗(為了能看得更清楚一點(diǎn),我用了(?'group')的語(yǔ)法):

<         #最外層的左括號(hào) [^<>]*     #最外層的左括號(hào)后面的不是括號(hào)的內(nèi)容 (  (   (?'Open'<) #碰到了左括號(hào),在黑板上寫一個(gè)"Open"   [^<>>]*   #匹配左括號(hào)后面的不是括號(hào)的內(nèi)容  )+  (   (?'-Open'>) #碰到了右括號(hào),擦掉一個(gè)"Open"   [^<>]*   #匹配右括號(hào)后面不是括號(hào)的內(nèi)容  )+ )* (?(Open)(?!))  #在遇到最外層的右括號(hào)前面,判斷黑板上還有沒(méi)有沒(méi)擦掉的"Open";如果有,則匹配失敗>         #最外層的右括號(hào)

我為什么寫這篇文章

看了上面的介紹,你明白了嗎?在我未理解正則表達(dá)式匹配原理之前,看上面對(duì)于平衡組的介紹,似懂非懂,且只能當(dāng)做模板記住,而不能靈活運(yùn)用。因此查閱大量有關(guān)正則方面的資料,這里尤其感謝lxcnn的技術(shù)文檔及《精通正則表達(dá)式》這本書,讓我對(duì)正則表達(dá)式有了更深入、更系統(tǒng)的理解,因此,在它們的基礎(chǔ)之上,我就結(jié)合自己的學(xué)習(xí)經(jīng)歷做個(gè)小結(jié),一來(lái)做為學(xué)習(xí)筆記存檔,另外,如果能解決你的疑惑,也是件讓人高興的事。
我先暫不分析上面的代碼,先講解一下關(guān)于平衡組相關(guān)的概念及知識(shí)。
下面表達(dá)式匹配測(cè)試工具為:Expresso,本站也提供它的完美破解版下載。

平衡組的概念及作用

平衡組,故名思義,平衡即對(duì)稱,主要是結(jié)合幾種正則語(yǔ)法規(guī)則,提供對(duì)配對(duì)出現(xiàn)的嵌套結(jié)構(gòu)的匹配。平衡組有狹義與廣義兩種定義,狹義平衡組指(?Expression) 語(yǔ)法,而廣義平衡組并不是固定的語(yǔ)法規(guī)則,而是幾種語(yǔ)法規(guī)則的綜合運(yùn)用,我們平時(shí)所說(shuō)的平衡組通常指的是廣義平衡組。本文中如無(wú)特殊說(shuō)明,平衡組這種簡(jiǎn)寫指的是廣義平衡組。
平衡組的匹配原理
平衡組的匹配原理可以用堆棧來(lái)解釋,先舉個(gè)例子,再根據(jù)例子進(jìn)行解釋。

源字符串:a+(b*(c+d))/e+f-(g/(h-i))*j
正則表達(dá)式:((?<Open>/()|(?<−Open>)|[^()])*(?(Open)(?!))/)
需求說(shuō)明:匹配成對(duì)出現(xiàn)的()中的內(nèi)容
輸出:(b*(c+d)) 和 (g/(h-i))
我將上面正則表達(dá)式代碼分行寫,并加上注釋,這樣看起來(lái)有層次,而且方便

 /(        #普通字符“(”  (       #分組構(gòu)造,用來(lái)限定量詞“*”修飾范圍   (?<Open>/() #命名捕獲組,遇到開(kāi)括弧“Open”計(jì)數(shù)加1   |      #分支結(jié)構(gòu)   (?<-Open>/)) #狹義平衡組,遇到閉括弧“Open”計(jì)數(shù)減1   |      #分支結(jié)構(gòu)   [^()]+    #非括弧的其它任意字符  )*       #以上子串出現(xiàn)0次或任意多次  (?(Open)(?!)) #判斷是否還有“Open”,有則說(shuō)明不配對(duì),什么都不匹配 /)       #普通閉括弧

對(duì)于一個(gè)嵌套結(jié)構(gòu)而言,開(kāi)始和結(jié)束標(biāo)記都是確定的,對(duì)于本例開(kāi)始為“(”,結(jié)束為“)”,那么接下來(lái)就是考察中間的結(jié)構(gòu),中間的字符可以劃分為三類,一類是“(”,一類是“)”,其余的就是除這兩個(gè)字符以外的任意字符。

那么平衡組的匹配原理就是這樣的

1、先找到第一個(gè)“(”,作為匹配的開(kāi)始。即上面的第1行,匹配了:a+(b*(c+d))/e+f-(g/(h-i))*j (紅色顯示部分)

2、在第1步以后,每匹配到一個(gè)“(”,就入棧一個(gè)Open捕獲組,計(jì)數(shù)加1

3、在第1步以后,每匹配到一個(gè)“)”,就出棧最近入棧的Open捕獲組,計(jì)數(shù)減1

也就是講,上面的第一行正則“/(”匹配了:a+(b*(c+d))/e+f-(g/(h-i))*j (紅色顯示部分)
然后,匹配到c前面的“(”,此時(shí),計(jì)數(shù)加1;繼續(xù)匹配,匹配到d后面的“)”,計(jì)算減1;——注意嘍:此時(shí)堆棧中的計(jì)數(shù)是0,正則還是會(huì)向前繼續(xù)匹配的,但是,如果匹配到“)”的話,比如,這個(gè)例子中d))(紅色顯示的括號(hào))——引擎此時(shí)將控制權(quán)交給(?(Open)(?!)),判斷堆棧中是否為0,如果為0,則執(zhí)行匹配“no”分支,由于這個(gè)條件判斷結(jié)構(gòu)中沒(méi)有“no”分支,所以什么都不做,把控制權(quán)交給接下來(lái)的“/)”
這個(gè)正則表達(dá)式“/)”可匹配接下來(lái)的),即b))(紅色顯示的括號(hào))

4、后面的 (?(Open)(?!))用來(lái)保證堆棧中Open捕獲組計(jì)數(shù)是否為0,也就是“(”和“)”是配對(duì)出現(xiàn)的

5、最后的“)”,作為匹配的結(jié)束

匹配過(guò)程

首先匹配第一個(gè)“(”,然后一直匹配,直到出現(xiàn)以下兩種情況之一時(shí),把控制權(quán)交給(?(Open)(?!)):
a)堆棧中Open計(jì)數(shù)已為0,此時(shí)再遇到“)”
b)匹配到字符串結(jié)束符
這時(shí)控制權(quán)交給(?(Open)(?!)),判斷Open是否有匹配,由于此時(shí)計(jì)數(shù)為0,沒(méi)有匹配,那么就匹配“no”分支,由于這個(gè)條件判斷結(jié)構(gòu)中沒(méi)有“no”分支,所以什么都不做,把控制權(quán)交給接下來(lái)的“/)”
如果上面遇到的是情況a),那么此時(shí)“/)”可以匹配接下來(lái)的“)”,匹配成功;
如果上面遇到的是情況b),那么此時(shí)會(huì)進(jìn)行回溯,直到“/)”匹配成功為止,否則報(bào)告整個(gè)表達(dá)式匹配失敗。
由于.NET中的狹義平衡組“(?<Close-Open>Expression)”結(jié)構(gòu),可以動(dòng)態(tài)的對(duì)堆棧中捕獲組進(jìn)行計(jì)數(shù),匹配到一個(gè)開(kāi)始標(biāo)記,入棧,計(jì)數(shù)加1,匹配到一個(gè)結(jié)束標(biāo)記,出棧,計(jì)數(shù)減1,最后再判斷堆棧中是否還有Open,有則說(shuō)明開(kāi)始和結(jié)束標(biāo)記不配對(duì)出現(xiàn),不匹配,進(jìn)行回溯或報(bào)告匹配失敗;如果沒(méi)有,則說(shuō)明開(kāi)始和結(jié)束標(biāo)記配對(duì)出現(xiàn),繼續(xù)進(jìn)行后面子表達(dá)式的匹配。
需要對(duì)“(?!)”進(jìn)行一下說(shuō)明,它屬于順序否定環(huán)視,完整的語(yǔ)法是“(?!Expression)”。由于這里的“Expression”不存在,表示這里不是一個(gè)位置,所以試圖嘗試匹配總是失敗的,作用就是在Open不配對(duì)出現(xiàn)時(shí),報(bào)告匹配失敗。

下面在看個(gè)例子:

<table><tr><td id="td1"> </td><td id="td2"><table><tr><td>snhame</td><td>f</td></tr></table></td><td></td></tr> </table>

以上為部分的HTML代碼.現(xiàn)在我們的問(wèn)題是要提取出其<td id="td2">的<td>標(biāo)簽并將其刪除掉,以往我們慣用的方法都是直接去取,像<td/s*id="td2">[/s/S]+?/</td>,不過(guò)問(wèn)題出來(lái)了,我們提取到的不是我們想要的內(nèi)容,而是

<td id="td2"><table><tr><td>snhame</td>

原因也很簡(jiǎn)單,它和離他最近的</td>標(biāo)簽匹配上了,不過(guò)它不知道這個(gè)標(biāo)簽不是它的-_-,是不是就是?符號(hào)的原因呢,我們?nèi)サ糇屗麩o(wú)限制貪婪,可這下問(wèn)題更大了,什么亂七八糟的東東它都匹配到了

<td id="td2"><table><tr><td>snhame</td><td>f</td></tr></td><td></td>

這個(gè)結(jié)果也不是我們想要的。那么我就用“平衡組”來(lái)解決吧。

<td/s*id="td2"[^>]*>((?<mm><td[^>]*>)+|(?<-mm></td>)|[/s/S])*?(?(mm)(?!))</td>

匹配的結(jié)果是

<td id="td2"><table><tr><td>snhame</td><td>f</td></tr></table></td><td></td>

這正是我們想要的
注意,我開(kāi)始寫成這樣的方式

<td/s*id="td2"[^>]*>((?<mm><td[^>]*>)+|(?<-mm></td>)|[/s/S])*(?(mm)(?!))</td> 

匹配的結(jié)果是

<td id="td2"><table><tr><td>snhame</td><td>f</td></tr></table></td><td></td>

一個(gè)問(wèn)題
以下代碼只是做為一個(gè)問(wèn)題探討
文本內(nèi)容:e+f(-(g/(h-i))*j

正則表達(dá)式:

/( (  (?<mm>/()  |  (?<-mm>/))  |  . )*? (?(mm)(?!))/)

匹配的結(jié)果是:(-(g/(h-i))

 

注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到正則表達(dá)式頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产精品久久久久久久久久东京 | 激情黄页| 成人做爰s片免费看网站 | 久久成人视屏 | 蜜桃麻豆视频 | 8x成人在线电影 | 福利免费视频 | 狠狠干天天操 | 亚洲综合视频网站 | 综合国产一区 | 亚洲九九爱 | 精品黑人一区二区三区国语馆 | 久久亚洲成人网 | 农村少妇吞精夜夜爽视频 | 免费一区二区三区 | 国产一区二区视频在线播放 | 黄色99视频 | 国产在线精品一区二区不卡 | 在线播放亚洲视频 | 成人视屏在线 | 国产精品一区二区三区在线看 | 国产精品99久久久久久大便 | 精品亚洲夜色av98在线观看 | 日韩av日韩 | 国产一区免费在线 | 蝌蚪久久窝 | 香蕉视频网站在线观看 | 一级免费观看 | 看免费的毛片 | 色网站免费观看 | 宅男噜噜噜66一区二区 | 国产成人精品一区二区仙踪林 | av中文在线观看 | 久久精品视频2 | 精品亚洲福利一区二区 | 一本色道久久99精品综合蜜臀 | 一级做a爱片性色毛片 | 欧美成人二区 | 欧美福利视频一区二区 | 精品999www| 午夜爱爱福利 |