使用正則表達式匹配嵌套Html標籤
正則表達式是做文本解析工作必不可少的技能。如Web伺服器日誌分析,網頁前端開發等。很多高級文本編輯器都支持正則表達式的一個子集,熟練掌握正則表達式,經常能夠使你的一些工作事半功倍。例如統計代碼行數,只需一個正則就搞定。嵌套Html標籤的匹配是正則表達式應用中一個比較難的話題,因為它涉及到的正則語法比較多,也比較難。因此也就更有研究的價值。
先確定我們要解決的問題——從一段Html文本中找出特定id的標籤的innerHTML
我們可以這樣想,先匹配最前面的起始標籤,假設是div吧(<div),然後一旦遇到嵌套div,就「壓入堆棧」,然後一遇到div結束標籤了,就「彈出堆棧」。如果遇到結束標籤的時候,堆棧裡面已經沒有東西了,那麼匹配結束,此結束標籤為正確的閉合標籤。
這裡假設我們要匹配的文本是一段合法的Html文本
<div id="myID">
<div class="s-sub">
<ul>
<li class="s-hw"><a href="http://consumer.huawei.com/cn/" target="_blank">華為官網</a></li>
<li class="s-honor"><a href="http://www.honor.cn/" target="_blank">華為榮耀</a></li>
<li class="s-emui"><a href="http://emui.huawei.com/cn/" target="_blank">EMUI</a></li>
<li class="s-appstore"><a href="http://appstore.huawei.com/" target="_blank">應用市場</a></li>
<li class="s-cloud"><a href="http://cloud.huawei.com/cn" target="_blank">雲服務</a></li>
<li class="s-developer"><a href="http://developer.huawei.com/" target="_blank">開發者聯盟</a></li>
<li class="s-club"><a href="http://club.huawei.com" target="_blank">花粉俱樂部</a></li>
</ul>
</div>
<p>test text</p>
<div>
<p>test text</p>
</div>
</div>
匹配起始標籤
起始標籤特徵很好提取,以尖括弧打頭,然後跟著一連串英文字母,然後一大串屬性中(非尖括弧字元)匹配id(不區分大小寫)=myID。需要注意的是,myID可以被雙引號或者單引號包裹,也可以什麼都不加。正則如下:
<(?<HtmlTag>[w]+)[^>]*s[iI][dD]=(?<Quote>[""]?)myID(?(Quote)k<Quote>)[^>]*?(/>|>
上面的正則表達式需要做幾點說明:
1. <尖括弧在正則中算是一個特殊字元,在顯式捕獲分組中用它將分組名括起來。但是因為開頭的尖括弧在此上下文下並不會出現解析歧義,因此加不加轉義符效果是一樣的。
2. (?<GroupName>RegEx)格式定義一個命名分組,我們在上面定義了一個HtmlTag的標籤分組,用來存放匹配到的Html標籤名。Quote分組是用來給後面的匹配使用的。
3. (?(GroupName)Then|Else)是條件語句,表示當捕獲到GroupName分組時執行Then匹配,否則執行Else匹配。上面的正則中,我們先嘗試匹配footer字元串左邊的引號,並將其存入LeftQuote分組中,然後在footer右側進行條件解析,如果之前匹配到LeftQuote分組,那麼右側也應該批評LeftQuote分組。這樣一來,我們就能精確匹配id的各種情況了。
匹配閉合標籤
((?<Nested><k<HtmlTag>[^>]*>)|</k<HtmlTag>>(?<-Nested>)|.*?)*</k<HtmlTag>>
在成功匹配到起始標籤之後,後面的Html文本可以分為三種情況:
A. 匹配到嵌套div起始標籤<div,這個時候,需要將其捕獲到Nested分組。
B. 匹配到嵌套div起始標籤的閉合標籤,這個時候,需要將之前的Nested分組釋放
C. 其他任意文本。注意,需要使用.*?方式關閉貪婪匹配,否則最後的閉合標籤可能會過度匹配
使用(RegEx1|RegEx2|RegEx3)*這種方式,可以將幾個條件以或的形式組合起來,然後再取若干次匹配結果,最終再匹配閉合標籤。其中(?<-Nested>)是表示釋放之前捕獲的Nested分組。確切的語法是(?<N-M>)即使用N分組替換掉M分組,如果N分組沒有指定或不存在,則釋放M分組。
完整的正則表達式為:
<(?<HtmlTag>[w]+)[^>]*s[iI][dD]=(?<Quote>[""]?)myID(?(Quote)k<Quote>)[^>]*?(/>|>((?<Nested><k<HtmlTag>[^>]*>)|</k<HtmlTag>>(?<-Nested>)|.*?)*</k<HtmlTag>>)
※netty整合springMVC,實現高效的HTTP服務請求
※餓了么大數據計算引擎實踐與應用
TAG:程序員小新人學習 |