2011-02-08 71 views
4

我知道你在想什麼 - 「哦,我的上帝,認真,不再」 - 但請耐心等待,我的問題不僅僅是標題。在我們開始之前,我保證我永遠不會嘗試用正則表達式解析任意的HTML,或者詢問其他人如何。擴展正則表達式實現可以解析HTML嗎?

這裏解釋了爲什麼你不能這樣做的所有很多很多答案都依賴於正則表達式的正式定義。他們解析常規語言,HTML是上下文無關的,但不是常規的,所以你不能這樣做。但我也聽說很多正則表達式在各種語言中的應用並不嚴格,它們會帶來額外的技巧,超出正式正則表達式的界限。

因爲我不知道任何特定的實現細節,比如Perl,我的問題是:

  1. 的正則表達式的工具,特點是​​不正常嗎?它是後面的參考嗎?他們找到哪種語言?
  2. 這些額外的技巧是否足以解析所有上下文無關的語言?
  3. 如果#2的「否」,那麼這些額外功能究竟是否涵蓋了正式的類別或語言類別?我們怎麼能夠很快地知道我們試圖解決的問題是否在我們不一定正則表達式的力量之內?
+4

哦,我的上帝,認真,不會再 – phihag 2011-02-08 13:39:40

回答

10

回答你的問題是,是,所謂的「擴展的正則表達式」 - 這是也許比正式意義上的正則表達式更恰當地稱爲模式 - 如在Perl和PCRE發現是indeed capable of recursive descent parsing of context-free grammars

This posting’s這一對方法說明了在X/HTML中應用正則表達式並沒有太多理論上的實際限制。那裏給出的第一種方法,就是那種天真的方法,更像是你在大多數進行這種嘗試的程序中容易找到的方法。這可以通過非常少的努力來處理明確定義的,非泛型的X/HTML。這是它的最佳應用,就像開放式X/HTML是最糟糕的一樣。

第二種方法,標記爲嚮導,使用實際語法進行分析。因此,它與任何其他語法方法一樣強大。然而,它也遠遠超出了絕大多數休閒程序員的權力。它也有風險重新創造一個負面利益的完美的輪子。我寫了它來顯示什麼可以完成,但在哪些情況下幾乎沒有任何永遠應該完成。我希望向人們展示爲什麼他們想要在開放式X/HTML上使用解析器,通過向他們展示即使使用當前可用的一些最強大的模式匹配工具,甚至可以接近正確的程度。

很多人誤以爲我的帖子是主張與我實際上所說的相反。請不要誤解:我的意思是使用起來太複雜了。這是反例證明。我曾希望通過展示如何用正則表達式來實現,人們會意識到他們爲什麼要做而不是想要走這條路。儘管所有的事情都是可能的,但並非所有事情都是有利的。

我個人的經驗法則是,如果所需的正則表達式只是第一個類別,我可以使用它,但是如果它需要第二類的完全語法處理,我使用別人已經編寫的解析器。所以即使我可以寫一個解析器,我看沒有理由這樣做,並且很多不會。

當了精心設計的具有明確目的,圖案可以更resisilient格式錯誤的X/HTML不是現成的現成解析器往往是,特別是如果你沒有真正的機會搞出說解析器,使他們對網絡瀏覽器傾向於容忍的常見故障情況更具適應性,但驗證人卻不能。然而,我上面提供的語法模式僅爲格式良好但合理的通用HTML設計(儘管沒有實體替換,很容易添加)。解析器中的錯誤恢復完全是一個單獨的問題,決不是一個愉快的問題。

模式,尤其是大多數人習慣於看到和使用的更常見的非語法的模式,更適合一次抓取離散塊,而不是用於生成完整的句法分析。換句話說,正則表達式對於lexing來說通常比​​解析更有效。沒有語法正則表達式,你不應該嘗試解析語法。

但是不要太過分。我當然並不是想暗示你應該立即轉向一個完整的解析器,因爲你想解決一些遞歸定義的問題。這類事情最容易也是最常見的例子是檢測嵌套項目的模式,如圓括號。這是非常常見的,我只是撲通下來一些簡單的像這樣在我的代碼,並用它做:

# delete all nested parens 
s/\((?:[^()]*+|(?0))*\)//g; 
2

是的,問題的擴展是反向引用,他們在技術上使「正則表達式」NP完成,請參閱Wikipedia paragraph

+0

NP完全性是指計算複雜性,不解析能力。我認爲這是該頁面中的錯誤,因爲它是在發佈此答案時發生的。目前的版本似乎已經修復了它 - 現在它說它們能夠解析上下文敏感的語言。 – hdgarrood 2015-04-03 16:35:41