這篇文章主要介紹正則表達式中平衡組的示例分析,文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!
10年積累的成都網(wǎng)站建設(shè)、成都網(wǎng)站制作經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計后付款的網(wǎng)站建設(shè)流程,更有河?xùn)|免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。一般正則教程中對平衡組的介紹
如果想要匹配可嵌套的層次性結(jié)構(gòu)的話,就得使用平衡組了。舉個例子吧,如何把“xx <aa <bbb> <bbb> aa> yy”這樣的字符串里,最長的尖括號內(nèi)的內(nèi)容捕獲出來?
這里需要用到以下的語法構(gòu)造:(?<group>)
把捕獲的內(nèi)容命名為group,并壓入堆棧(?<-group>)
從堆棧上彈出最后壓入堆棧的名為group的捕獲內(nèi)容,如果堆棧本來為空,則本分組的匹配失敗(?(group)yes|no)
如果堆棧上存在以名為group的捕獲內(nèi)容的話,繼續(xù)匹配yes部分的表達式,否則繼續(xù)匹配no部分(?!)
順序否定環(huán)視,由于沒有后綴表達式,試圖匹配總是失敗
如果你不是一個程序員(或者你是一個對堆棧的概念不熟的程序員),你就這樣理解上面的三種語法吧:第一個就是在黑板上寫一個(或再寫一個)"group",第二個就是從黑板上擦掉一個"group",第三個就是看黑板上寫的還有沒有"group",如果有就繼續(xù)匹配yes部分,否則就匹配no部分。
我們需要做的是每碰到了左括號,就在黑板上寫一個"group",每碰到一個右括號,就擦掉一個,到了最后就看看黑板上還有沒有-如果有那就證明左括號比右括號多,那匹配就應(yīng)該失?。榱四芸吹酶宄稽c,我用了(?'group')的語法):
< #最外層的左括號 [^<>]* #最外層的左括號后面的不是括號的內(nèi)容 ( ( (?'Open'<) #碰到了左括號,在黑板上寫一個"Open" [^<>>]* #匹配左括號后面的不是括號的內(nèi)容 )+ ( (?'-Open'>) #碰到了右括號,擦掉一個"Open" [^<>]* #匹配右括號后面不是括號的內(nèi)容 )+ )* (?(Open)(?!)) #在遇到最外層的右括號前面,判斷黑板上還有沒有沒擦掉的"Open";如果有,則匹配失敗 > #最外層的右括號
我為什么寫這篇文章
看了上面的介紹,你明白了嗎?在我未理解正則表達式匹配原理之前,看上面對于平衡組的介紹,似懂非懂,且只能當(dāng)做模板記住,而不能靈活運用。因此查閱大量有關(guān)正則方面的資料,這里尤其感謝lxcnn的技術(shù)文檔及《精通正則表達式》這本書,讓我對正則表達式有了更深入、更系統(tǒng)的理解,因此,在它們的基礎(chǔ)之上,我就結(jié)合自己的學(xué)習(xí)經(jīng)歷做個小結(jié),一來做為學(xué)習(xí)筆記存檔,另外,如果能解決你的疑惑,也是件讓人高興的事。
我先暫不分析上面的代碼,先講解一下關(guān)于平衡組相關(guān)的概念及知識。
下面表達式匹配測試工具為:Expresso,本站也提供它的完美破解版下載。
平衡組的概念及作用
平衡組,故名思義,平衡即對稱,主要是結(jié)合幾種正則語法規(guī)則,提供對配對出現(xiàn)的嵌套結(jié)構(gòu)的匹配。平衡組有狹義與廣義兩種定義,狹義平衡組指(?Expression)
語法,而廣義平衡組并不是固定的語法規(guī)則,而是幾種語法規(guī)則的綜合運用,我們平時所說的平衡組通常指的是廣義平衡組。本文中如無特殊說明,平衡組這種簡寫指的是廣義平衡組。
平衡組的匹配原理
平衡組的匹配原理可以用堆棧來解釋,先舉個例子,再根據(jù)例子進行解釋。
源字符串:a+(b*(c+d))/e+f-(g/(h-i))*j
正則表達式:((?<Open>\()|(?<?Open>)|[^()])*(?(Open)(?!))\)
需求說明:匹配成對出現(xiàn)的()中的內(nèi)容
輸出:(b*(c+d)) 和 (g/(h-i))
我將上面正則表達式代碼分行寫,并加上注釋,這樣看起來有層次,而且方便
\( #普通字符“(” ( #分組構(gòu)造,用來限定量詞“*”修飾范圍 (?<Open>\() #命名捕獲組,遇到開括弧“Open”計數(shù)加1 | #分支結(jié)構(gòu) (?<-Open>\)) #狹義平衡組,遇到閉括弧“Open”計數(shù)減1 | #分支結(jié)構(gòu) [^()]+ #非括弧的其它任意字符 )* #以上子串出現(xiàn)0次或任意多次 (?(Open)(?!)) #判斷是否還有“Open”,有則說明不配對,什么都不匹配 \) #普通閉括弧
對于一個嵌套結(jié)構(gòu)而言,開始和結(jié)束標(biāo)記都是確定的,對于本例開始為“(”,結(jié)束為“)”,那么接下來就是考察中間的結(jié)構(gòu),中間的字符可以劃分為三類,一類是“(”,一類是“)”,其余的就是除這兩個字符以外的任意字符。
那么平衡組的匹配原理就是這樣的
1、先找到第一個“(”,作為匹配的開始。即上面的第1行,匹配了:a+(b*(c+d))/e+f-(g/(h-i))*j (紅色顯示部分)
2、在第1步以后,每匹配到一個“(”,就入棧一個Open捕獲組,計數(shù)加1
3、在第1步以后,每匹配到一個“)”,就出棧最近入棧的Open捕獲組,計數(shù)減1
也就是講,上面的第一行正則“\(”匹配了:a+(b*(c+d))/e+f-(g/(h-i))*j
(紅色顯示部分)
然后,匹配到c前面的“(”,此時,計數(shù)加1;繼續(xù)匹配,匹配到d后面的“)”,計算減1;——注意嘍:此時堆棧中的計數(shù)是0,正則還是會向前繼續(xù)匹配的,但是,如果匹配到“)”的話,比如,這個例子中d))(紅色顯示的括號)——引擎此時將控制權(quán)交給(?(Open)(?!))
,判斷堆棧中是否為0,如果為0,則執(zhí)行匹配“no”分支,由于這個條件判斷結(jié)構(gòu)中沒有“no”分支,所以什么都不做,把控制權(quán)交給接下來的“\)”
這個正則表達式“\)”可匹配接下來的),即b))(紅色顯示的括號)
4、后面的 (?(Open)(?!))
用來保證堆棧中Open捕獲組計數(shù)是否為0,也就是“(”和“)”是配對出現(xiàn)的
5、最后的“)”,作為匹配的結(jié)束
匹配過程
首先匹配第一個“(”,然后一直匹配,直到出現(xiàn)以下兩種情況之一時,把控制權(quán)交給(?(Open)(?!)):
a)堆棧中Open計數(shù)已為0,此時再遇到“)”
b)匹配到字符串結(jié)束符
這時控制權(quán)交給(?(Open)(?!))
,判斷Open是否有匹配,由于此時計數(shù)為0,沒有匹配,那么就匹配“no”分支,由于這個條件判斷結(jié)構(gòu)中沒有“no”分支,所以什么都不做,把控制權(quán)交給接下來的“\)”
如果上面遇到的是情況a),那么此時“\)”可以匹配接下來的“)”,匹配成功;
如果上面遇到的是情況b),那么此時會進行回溯,直到“\)”匹配成功為止,否則報告整個表達式匹配失敗。
由于.NET中的狹義平衡組“(?<Close-Open>Expression)
”結(jié)構(gòu),可以動態(tài)的對堆棧中捕獲組進行計數(shù),匹配到一個開始標(biāo)記,入棧,計數(shù)加1,匹配到一個結(jié)束標(biāo)記,出棧,計數(shù)減1,最后再判斷堆棧中是否還有Open,有則說明開始和結(jié)束標(biāo)記不配對出現(xiàn),不匹配,進行回溯或報告匹配失敗;如果沒有,則說明開始和結(jié)束標(biāo)記配對出現(xiàn),繼續(xù)進行后面子表達式的匹配。
需要對“(?!)
”進行一下說明,它屬于順序否定環(huán)視,完整的語法是“(?!Expression)
”。由于這里的“Expression”不存在,表示這里不是一個位置,所以試圖嘗試匹配總是失敗的,作用就是在Open不配對出現(xiàn)時,報告匹配失敗。
下面在看個例子:
<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)在我們的問題是要提取出其<td id="td2">的<td>標(biāo)簽并將其刪除掉,以往我們慣用的方法都是直接去取,像<td\s*id="td2">[\s\S]+?\</td>,不過問題出來了,我們提取到的不是我們想要的內(nèi)容,而是
<td id="td2"> <table> <tr> <td>snhame</td>
原因也很簡單,它和離他最近的</td>標(biāo)簽匹配上了,不過它不知道這個標(biāo)簽不是它的-_-,是不是就是?符號的原因呢,我們?nèi)サ糇屗麩o限制貪婪,可這下問題更大了,什么亂七八糟的東東它都匹配到了
<td id="td2"> <table> <tr> <td>snhame</td> <td>f</td> </tr> </td> <td></td>
這個結(jié)果也不是我們想要的。那么我就用“平衡組”來解決吧。
<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>
這正是我們想要的
注意,我開始寫成這樣的方式
<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>
一個問題
以下代碼只是做為一個問題探討
文本內(nèi)容:e+f(-(g/(h-i))*j
正則表達式:
\( ( (?<mm>\() | (?<-mm>\)) | . )*? (?(mm)(?!)) \)
匹配的結(jié)果是:(-(g/(h-i))
以上是“正則表達式中平衡組的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
文章題目:正則表達式中平衡組的示例分析-創(chuàng)新互聯(lián)
文章地址:http://m.rwnh.cn/article14/esjge.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、標(biāo)簽優(yōu)化、品牌網(wǎng)站制作、網(wǎng)站導(dǎo)航、網(wǎng)站設(shè)計公司、虛擬主機
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容