2011-02-08 8 views
4

私はあなたが思っていることを知っています - "ああ、私の神、真剣に、もう一度" - しかし、私と一緒に耐えてください、私の質問はタイトル以上です。始める前に、私は正規表現で任意のHTMLを解析しようとしないことを約束します。拡張正規表現の実装でHTMLを解析できますか?

これを行うことができない理由を説明する多くの多くの回答は、正規表現の正式な定義に依存しています。彼らは規則的な言語を解析します、HTMLは文脈自由ですが、規則的ではないので、あなたはそれをすることができません。しかし、私はまた、さまざまな言語での正規表現の実装が厳密に規則的ではないと聞きました。正式な正規表現の境界を超えて余計なトリックが付いてきます。私は、任意の特定の実装の詳細を知らないので

、Perlなど、私の質問は以下のとおりです。正規表現のツールの特徴

  1. が非正規ですか?それは後の参照ですか?どの言語でそれらが見つかりましたか?
  2. これらの余分なトリックは、すべてのコンテキストフリー言語を解析するのに十分ですか?
  3. #2に「いいえ」と答えた場合、これらの追加機能が正確にカバーする正式なカテゴリまたは言語クラスがありますか?私たちが解決しようとしている問題が、必ずしも正規表現ではないという力の範囲内にあるかどうかを、すぐにどのように知ることができますか?
+4

の神私のああ、真剣に、再び – phihag

答えて

10

あなたの質問への答えはイエス、いわゆる「拡張正規表現」ということです - おそらくより適切に正式な意味での正規表現よりも、パターンと呼ばれている - PerlやPCREに見られるようにindeed capable of recursive descent parsing of context-free grammarsです。

This posting’s X/HTMLに正規表現を適用するには実用的な限界としてあまり理論的ではありません。ナイーブにラベル付けされた最初のアプローチは、そうした試みを行うほとんどのプログラムで見つけやすいソートに似ています。これは、よく定義された非ジェネリックのX/HTMLで動作するようにすることができます。オープンエンドのX/HTMLが最悪の場合と同じように、その最高のアプリケーションです。

wizardlyとラベル付けされた第2のアプローチは、実際の文法を解析に使用します。したがって、他の文法的なアプローチと同じくらい強力です。しかし、圧倒的多数のカジュアルなプログラマーの力をはるかに超えています。また、負の利益のために完全に細かい輪を再作成するリスクもあります。私はを行うことができることを示すためにそれを書いたが、事実上全く何もなしでこれまでにを行うべきである。私は、オープンエンドのX/HTML上でパーザを使う理由を示すために、現在入手可能な最もパワフルなパターンマッチング機能のいくつかを使っていても、どれほど難しいと感じるのかを示すことを望みました。

私が実際に言っていることの反対を何らかの形で主張するものとして、多くの人が私の投稿を誤解しています。間違ってはいけません。私は使用するにはあまりにも複雑すぎると言っています。それは反例による証拠です。私は正規表現を使ってそれを行う方法を示すことによって、人々はなぜ彼らがをしなかったのかを理解し、がその道を下りたいと望んでいた。すべてのことが可能ですが、すべてが便宜的ではありません。

私の個人的な経験則では、必要な正規表現が最初のカテゴリのみの場合、私はそれをうまく使うかもしれませんが、2番目のカテゴリの完全な文法処理が必要な場合は、 。だから私はパーサーを書くことができますが、私はそうする理由はなく、たくさんありません。

慎重にその明確な目的のために作られた場合には、パターン既製のパーサは、あなたがそれらを作ると言わパーサーをハックする本当の機会を持っていない場合は特に、する傾向があるよりも、不正な形式のX/HTMLによりresisilientすることができWebブラウザでは許容される傾向がありますが、バリデータでは許容されない一般的な失敗のケースに対して、より弾力性があります。しかし、私が上記で提供した文法パターンは、整形式だが合理的に汎用的なHTML(エンティティの置き換えがなくても十分に追加されているにすぎない)用に設計されています。パーサーでのエラー回復は、全く別の問題であり、決して楽しいものではありません。

パターン、特にほとんどの人が見たり使い慣れているはるかに一般的な非文法的なパターンは、完全な構文分析を作成するよりも、個別のチャンクを1つずつ取り上げる方がはるかに適しています。言い換えれば、の正規表現は、通常、解析の場合よりもレキシングの方が効果的です。文法的正規表現がなければ、文法を解析しないでください。

しかしそれほど遠すぎないでください。再帰的に定義されたものに取り組んでいるからといって、すぐに完全なパーサに変えるべきであるということを意味するわけではありません。この種のものの中で最も簡単で最も一般的に見られる例は、括弧のようなネストされた項目を検出するパターンです。私はちょうど私のコードでは、このような単純なものを下にウンチし、それを使って行うことのためにそれは非常に一般的です:

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

はい、質問の拡張子は逆参照であり、技術的には「正規表現」NP完成品です(Wikipedia paragraphを参照)。

+0

NP-完全に電源を解析していない、計算の複雑さを意味しません。私は、この答えが掲載されたときのそのページのエラーだと思う。現在のバージョンはそれを修正したようだ - 今や彼らは文脈依存言語を解析する能力があると言っている。 – hdgarrood

関連する問題