html - online - regex test




RegExはXHTML自己完結型タグを除いてオープンタグにマッチします (20)

これらの開始タグのすべてに一致する必要があります:

<p>
<a href="foo">

しかし、これらはありません:

<br />
<hr class="foo" />

私はこれを思いつき、私はそれが正しいことを確認したかった。 私は唯一のazキャプチャしています。

<([a-z]+) *[^/]*?>

私はそれが言うと信じています:

  • 以下を見つける
  • azを1回以上見つけて(そしてキャプチャして)、次に
  • ゼロ個以上のスペースを見つけ、次に
  • 任意の文字を0回以上見つけ、貪欲で、 /を除いて
  • より大きい値を求める

私はその権利を持っていますか? さらに重要なことは、あなたはどう思いますか?



PHPでXMLとHTMLを解析するためにQueryPathを使用することをQueryPath勧めします。 これは基本的にjQueryと同じ構文ですが、サーバー側だけです。


免責事項 :オプションがある場合はパーサーを使用してください。 それは言った...

これはHTMLタグと一致する正規表現です(!):

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>

完璧ではないかもしれませんが、私はこのコードを多くのHTMLを通して実行しました。 それは<a name="badgenerator"">ような奇妙なものをキャッチしてウェブ上に<a name="badgenerator"">ことに注意してください。

私はそれが自己完結型タグと一致しないようにすると思います、あなたはKobiの否定的なKobiを使うかどちらかを使いたいです:

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+(?<!/\s*)>

もしそうであれば結合するだけです。

To downvoters:これは実際の製品の作業コードです。 私はこのページを読んでいる人は、HTML上で正規表現を使うことは社会的に受け入れられているという印象を受けるだろうとは思っていません。

警告 :この正規表現は、CDATAブロック、コメント、スクリプトとスタイル要素の存在下ではまだ解消されていることに注意してください。 良いニュースは、あなたは正規表現を使用してそれらを取り除くことができます...


PHPでこれが必要な場合:

PHPのDOM functionsそれが適切にXMLにフォーマットされていない限り、正常に動作しません。彼らの使用が他の人類にとってどれほど優れていても。

simplehtmldomは良いですが、私はそれがバグであることが分かりました、そしてそれはかなり重いです[大きなページでクラッシュします。]

私はQueryPath使用していないので、その有用性についてコメントすることはできません。

私のDOMParserはリソースに非常に軽く、しばらくの間楽しんでいます。シンプルで覚えやすい。

PythonとJavaでは、同様のリンクが投稿されました。

ダウンローダの場合、XMLパーサーが実際の使用に耐えられないことが証明されたときに私はクラスを書きました。宗教的なdownvotingはちょうど有用な答えが掲示されるのを妨げる - 質問の視点の中で物事を保ってください。


ここに解決策があります:

<?php
// here's the pattern:
$pattern = '/<(\w+)(\s+(\w+)\s*\=\s*(\'|")(.*?)\\4\s*)*\s*(\/>|>)/';

// a string to parse:
$string = 'Hello, try clicking <a href="#paragraph">here</a>
    <br/>and check out.<hr />
    <h2>title</h2>
    <a name ="paragraph" rel= "I\'m an anchor"></a>
    Fine, <span title=\'highlight the "punch"\'>thanks<span>.
    <div class = "clear"></div>
    <br>';

// let's get the occurrences:
preg_match_all($pattern, $string, $matches, PREG_PATTERN_ORDER);

// print the result:
print_r($matches[0]);
?>

それを深くテストするために、私は以下のような自動クローズの文字列を入力しました:

  1. <hr />
  2. <br/>
  3. <br>

私もタグを入力しました:

  1. 1つの属性
  2. 複数の属性
  3. 値は単一引用符または二重引用符で囲まれた属性
  4. デリミタが二重引用符である場合は一重引用符を含む属性、
  5. "unpretty"属性は、 "="記号の前、後ろ、後ろの両方にスペースを入れてください。

上記の概念証明ではうまくいかないものを見つけたら、私はスキルを向上させるためにコードを分析することができます。

<編集>私は、ユーザーからの質問が自己終了タグの解析を避けることであることを忘れていました。この場合、パターンはより簡単になり、次のようになります。

$pattern = '/<(\w+)(\s+(\w+)\s*\=\s*(\'|")(.*?)\\4\s*)*\s*>/';

ユーザー@ridgerunnerは、パターンで引用符で囲まれていない属性値のない属性を許可しないことに気付きました。この場合、微調整を行うと次のパターンが得られます。

$pattern = '/<(\w+)(\s+(\w+)(\s*\=\s*(\'|"|)(.*?)\\5\s*)?)*\s*>/';

</ EDIT>

パターンを理解する

誰かがパターンについてもっと知りたいと思っているなら、私はいくつかの行を提供します:

  1. 最初の部分式(\ w +)はタグ名と一致します
  2. 2番目のサブ式には属性のパターンが含まれています。それはによって構成されます:
    1. 1つまたは複数の空白スペース\ s +
    2. 属性の名前(\ w +)
    3. 0個以上の空白スペース\ s *(空白を残すことも可能です)
    4. "="記号
    5. 再びゼロ個以上の空白
    6. ( "|")このパターンでは、PHPの文字列区切り文字と一致するため、一重引用符はエスケープされます。この部分式は、かっこでキャプチャされて参照できます再度属性のクロージャを解析する必要があります。そのため、非常に重要です。
    7. ほとんどのものと一致する属性の値。(。*?); この特定の構文では、グリーディマッチ(アスタリスクの後の疑問符)を使用して、RegExpエンジンは、このサブ式に続くもの以外のものにマッチする "先読み"のような演算子を有効にします
    8. ここで楽しいことが起こります:\ 4部分は後方参照演算子で、パターンの前に定義されている部分式を参照します。この場合は、最初の属性区切り文字である4番目の部分式を参照しています
    9. 0個以上の空白スペース\ s *
    10. アスタリスクで指定された0個以上の可能な出現の指定とともに、属性の部分式がここで終了します。
  3. その後、タグは ">"記号の前の空白で終わる可能性があるので、0個以上の空白は\ s *サブパターンと一致します。
  4. マッチさせるタグは、単純な ">"記号で終わるか、可能なXHTMLクロージャーで終わることがあります。これは、その前にスラッシュ(:> |>)を使用します。スラッシュはもちろん、正規表現の区切り文字と一致するため、エスケープされます。

小さなヒント:このコードをよりよく分析するには、HTMLの特殊文字をエスケープしないので、生成されたソースコードを調べる必要があります。


これらの人に耳を傾けないでください。 タスクをより小さな部分に分割すると、文脈自由文法を正規表現で完全に解析できます。 これらのそれぞれを順番に実行するスクリプトを使用して、正しいパターンを生成することができます。

  1. 停止問題を解く。
  2. 円を四角で囲む。
  3. O(log n)以下でTraveling Salesman問題を解く。 これ以上なら、RAMがなくなりエンジンがハングします。
  4. パターンはかなり大きくなるので、無作為にランダムなデータを圧縮するアルゴリズムがあることを確認してください。
  5. ほぼそこに - 全体をゼロで分けるだけです。 イージーピーシー。

私は最後の部分を自分で終わらせていないが、私は近くに近づいていることを知っている。 それは何らかの理由でCthulhuRlyehWgahnaglFhtagnExceptionをスローし続けます。したがって、VB 6に移植し、 On Error Resume Nextを使用します。 壁に開けられたこの奇妙なドアを調べたら、コードを更新します。 うーん。

PSピエール・ド・フェルマーもそれをやる方法を考え出したが、彼が書いていたマージンはコードにとって十分ではなかった。


シェルでは、以下を使用してHTMLを解析できHTML

  • しかしsed

    1. Turing.sed
    2. HTMLパーサー(宿題)を書く
    3. ???
    4. 利益!
  • html-xml-utilsパッケージからのhxselect

  • vim / exhtmlタグ間を簡単にジャンプできます )。たとえば、次のようになります。

    • 内部コードでスタイルタグを削除する:

      $ curl -s http://example.com/ | ex -s +'/<style.*/norm nvatd' +%p -cq! /dev/stdin
      
  • grep 、たとえば:

    • H1の外側のhtmlを抽出する:

      $ curl -s http://example.com/ | grep -o '<h1>.*</h1>'
      <h1>Example Domain</h1>
      
    • 本文を抽出する:

      $ curl -s http://example.com/ | tr '\n' ' ' | grep -o '<body>.*</body>'
      <body> <div> <h1>Example Domain</h1> ...
      
  • html2textからプレーンテキスト解析まで:

    • 解析テーブルのように:

      $ html2text foo.txt | column -ts'|'
      
  • xpathXML::XPath perlモジュール)を使って、 ここの例を見てください

  • perlまたはPython( @Gillesの例を参照)

  • 一度に複数のファイルを解析するには、以下を参照してください: シェル内の100個のHTMLソースコードファイルを解析するには?

関連(正規表現マッチを使用しない理由):


古代中国のストラテジスト、将軍、哲学者、サン・ツズはこう語った。

あなたが敵を知り、自分自身を知っていれば、1回の損失なしに100回の戦いで勝てると言われています。あなた自身だけを知っていて、あなたの相手を知っていないなら、勝つか失うかもしれません。あなた自身もあなたの敵も知らないなら、あなたは常に自分自身を危険にさらします。

この場合、あなたの敵はHTMLであり、あなたは自分自身か正規表現です。あなたは不規則な正規表現を持つPerlかもしれません。HTMLを知っている。自分自身を知っている。

私はHTMLの性質を説明する俳句を作った。

HTML has
complexity exceeding
regular language.

私はPerlの正規表現の本質を記述した俳句も作っています。

The regex you seek
is defined within the phrase
<([a-zA-Z]+)(?:[^>]*[^/]*)?>

最後に「/」を付けずにタグをマッチさせようとしているようです。 これを試して:

<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>

正規表現でHTMLを解析できないという答えは正しいが、ここでは適用しない。 OPは正規表現で1つのHTMLタグを解析したいだけで、正規表現で行うことができます。

しかし、提案された正規表現は間違っています:

<([a-z]+) *[^/]*?>

あなたが正規表現に何かを追加すると、バックトラックすることによって、 <a >>ような愚かなものにマッチさせることができます。 [^/]はあまりにも許容的です。 また、 [^/]*は空白にもマッチするので、 <space>*[^/]*は冗長であることにも注意してください。

私の提案は

<([a-z]+)[^>]*(?<!/)>

どこで(?<! ... )は、(Perlの正規表現では)負のルックバックがあります。 これは、 "a <、単語の後、>ではないもの、最後には/ではないかもしれないもの、>が続きます。

これは<a/ >ようなものです(元の正規表現と同じように)ので、より制限的なものが必要な場合は、スペースで区切られた属性のペアにマッチする正規表現を作成する必要があります。


私は、XML、 特にHTMLを解析する適切なツールはパーサであり、正規表現エンジンではないことに同意します 。 しかし、他の人が指摘しているように、正規表現を使用するとデータ形式がわかっていると、より速く簡単に作業を完了できることがあります。

マイクロソフトは実際に.NET Frameworkで正規表現のベストプラクティスに関するセクションを用意しており、特に入力ソースについて検討 しています

正規表現には制限がありますが、あなたは以下を考慮しましたか?

.NETフレームワークは、正規表現の場合、 グループ定義のバランシングをサポートしている点でユニークです。

このため、正規表現を使用してXMLを解析することができます。 ただし、 有効なXMLなければならないことに注意してください( ブラウザはHTMLを非常に寛容にし、HTML内部で不正なXML構文を許可します )。 これは、「バランシンググループ定義」によって正規表現エンジンがPDAとして動作することが可能になるため可能です。

上記の引用文献1の引用:

.NET正規表現エンジン

上で説明したように、適切にバランスの取れたコンストラクトは正規表現では記述できません。 ただし、.NETの正規表現エンジンでは、バランスの取れた構文を認識できるようにいくつかの構造が用意されています。

  • (?<group>) - キャプチャされた結果をネームグループを持つキャプチャスタックにプッシュします。
  • (?<-group>) - 一番上のキャプチャをキャプチャスタックから名前グループでポップします。
  • (?(group)yes|no) - 名前のグループを持つグループが存在する場合はyes部分に一致し、そうでなければ部分には一致しません。

これらの構成では、スタック操作の単純なバージョン(プッシュ、ポップ、および空)を本質的に許可することによって、.NETの正規表現で制限されたPDAをエミュレートできます。 単純な操作は、インクリメント、デクリメント、およびゼロとそれぞれほぼ同等です。 これにより、.NETの正規表現エンジンは、コンテキストフリー言語のサブセット、特に単純なカウンタだけを必要とする言語を認識することができます。 これにより、非伝統的な.NETの正規表現で、適切にバランスの取れた個々の構造を認識することができます。

次の正規表現を考えてみましょう。

(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
   <!-- .*? -->                  |
   <[^>]*/>                      |
   (?<opentag><(?!/)[^>]*[^/]>)  |
   (?<-opentag></[^>]*[^/]>)     |
   [^<>]*
)*
(?(opentag)(?!))

フラグを使用する:

  • 単線
  • IgnorePatternWhitespace(正規表現を崩してすべての空白を削除した場合は不要)
  • IgnoreCase(不要)

正規表現の説明(インライン)

(?=<ul\s+id="matchMe"\s+type="square"\s*>) # match start with <ul id="matchMe"...
(?>                                        # atomic group / don't backtrack (faster)
   <!-- .*? -->                 |          # match xml / html comment
   <[^>]*/>                     |          # self closing tag
   (?<opentag><(?!/)[^>]*[^/]>) |          # push opening xml tag
   (?<-opentag></[^>]*[^/]>)    |          # pop closing xml tag
   [^<>]*                                  # something between tags
)*                                         # match as many xml tags as possible
(?(opentag)(?!))                           # ensure no 'opentag' groups are on stack

より良い.NET正規表現テスターでこれを試すことができます

私はサンプルソースを使用しました:

<html>
<body>
<div>
   <br />
   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>
</div>
</body>
</html>

これは一致を見つけた:

   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>

実際にはこのように出てきました。

<ul id="matchMe" type="square">           <li>stuff...</li>           <li>more stuff</li>           <li>               <div>                    <span>still more</span>                    <ul>                         <li>Another &gt;ul&lt;, oh my!</li>                         <li>...</li>                    </ul>               </div>           </li>        </ul>

最後に、私はJeff Atwoodの記事「 Parsing Html The Cthulhu Way」を本当に楽しんでいました。 面白いことに、現在4k票を上回っているこの質問に対する答えを挙げています。


試してください:

<([^\s]+)(\s[^>]*?)?(?<!/)>

それはあなたのものに似ていますが、最後>はスラッシュの後にあってはならず、また受け入れますh1


HTML文書から何かをすばやく抽出する必要があるときは、Tidyを使用してXMLに変換し、XPathまたはXSLTを使用して必要なものを取得します。あなたの場合、次のようなものです:

//p/a[@href='foo']

W3Cは擬似正規表現形式での解析を説明しています:
W3C Link

以下のためのVaRのリンクをたどりQNameSAttribute鮮明な画像を取得します。
これに基づいて、タグを取り除くなどの処理を行うためのかなり良い正規表現を作成することができます。


ここでは、いくつかの不敬な正規表現を使ってHTMLを解析するPHPベースのパーサーがあります。このプロジェクトの著者として、正規表現でHTMLを解析することは可能だが、効率的ではないことを伝えることができます。サーバー側のソリューションが必要な場合(私のwp-Typography WordPressプラグインの場合と同じように)、これは機能します。


以前はHTMLParserというオープンソースツールを使用していました。これは、さまざまな方法でHTMLを解析するように設計されており、その目的に非常に適しています。HTMLを別のtreenodeとして解析することができ、簡単にAPIを使用してノードから属性を取得することができます。それをチェックし、これがあなたを助けることができるかどうかを確認してください。


私はあなたの正確な必要性を知っていませんが、もしあなたも.NETを使っているなら、あなたはHtml Agility Packを使うことができませんでしたか?

抜粋:

これは、 "Webから" HTMLファイルを解析できるようにする.NETコードライブラリです。パーサーは、「現実世界」の不正な形式のHTMLに対して非常に寛容です。


私は最近、JavaでHTMLサニタイザを書いた。これは、正規表現とJavaコードの混在したアプローチに基づいています。個人的には、正規表現とその愚かさ(可読性、保守性など)は嫌いですが、アプリケーションの適用範囲を狭めると、ニーズに合うかもしれません。とにかく、私のサニタイザは、HTMLタグ用のホワイトリストと、いくつかのスタイル属性用のブラックリストを使用します。

あなたの利便性のために私はプレイグラウンドを設定していますので、コードがあなたの要件に合っているかどうかテストすることができます:プレイグラウンドとJavaコード。あなたのフィードバックは高く評価されます。

私のブログでこの作品を説明している小さな記事があります:http : //roberto.open-lab.com


(X)HTMLを解析する正規表現方法の問題については、いくつかの制限について話したものの全てに答えは:ので、あなたは、この強力な武器の力を支配するのに十分な訓練を受けていない、誰もここで話したん再帰

RegExpには関係のない同僚がこのディスカッションに私に通知しました。

いくつかの投稿を読んだ後、私がやった最初のことは、このスレッドの "?R"文字列を探していたことです。2番目は「再帰」を検索することでした。
いいえ、聖なる牛、一致するものは見つかりませんでした。
パーサーが構築されている主なメカニズムについて誰も触れていないので、私はすぐに誰もその要点を理解していないことを知っていました。

(x)HTMLパーサが再帰を必要とする場合、再帰を伴わないRegExpパーサは目的には不十分です。それは単純な構造です。

RegExp黒い芸術は習得するのが難しいので、私たちの個人的な解決策を試して試しながら、一方の手でウェブ全体を捉えるために残した可能性はもっとあるかもしれません...まあ、私はそれについて確信しています:)

ここに魔法のパターンがあります:

$pattern = "/<([\w]+)([^>]*?)(([\s]*\/>)|(>((([^<]*?|<\!\-\-.*?\-\->)|(?R))*)<\/\\1[\s]*>))/s";

やってみなよ。
これはPHP文字列として書かれているので、 "s"修飾子はクラスに改行を含むようにします。
ここだPHPマニュアルのサンプルノート:私は1月に書いたReference

(そのメモでは、 "m"修飾子を間違って使用していましたが、^または$ anchorageが使用されていないため、RegExpエンジンによって破棄されても消去する必要があります)。

今、私たちは、より情報に基づいた観点から、この方法の限界について話すことができました:

  1. RegExpエンジンの特定の実装によれば、再帰はネストされたパターン数に制限がありますが、使用される言語に依存します
  2. 壊れた(x)HTMLは重大なエラーに陥ることはありませんが、それはサニタイズされていません。

とにかくそれはRegExpパターンだけですが、多くの強力な実装を開発する可能性を開示しています。
私はフレームワークで構築したテンプレートエンジンの再帰的降下パーサに電力を供給するためにこのパターンを書きました。実行時間やメモリ使用量の両方でパフォーマンスは素晴らしいです(同じ構文を使用する他のテンプレートエンジンとは関係ありません)。


<?php
$selfClosing = explode(',', 'area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed');

$html = '
<p><a href="#">foo</a></p>
<hr/>
<br/>
<div>name</div>';

$dom = new DOMDocument();
$dom->loadHTML($html);
$els = $dom->getElementsByTagName('*');
foreach ( $els as $el ) {
    $nodeName = strtolower($el->nodeName);
    if ( !in_array( $nodeName, $selfClosing ) ) {
        var_dump( $nodeName );
    }
}

出力:

string(4) "html"
string(4) "body"
string(1) "p"
string(1) "a"
string(3) "div"

基本的には、自己閉じている要素のノード名を定義し、HTMLライブラリ全体をDOMライブラリにロードし、すべての要素を取得し、ループスルーし、自己閉じていない要素をフィルタリングして除外します。

私はあなたがすでに正規表現をこの目的のために使うべきではないことをすでに知っていると確信しています。





xhtml