4

Regex のチュートリアルを見ていました。

このhtmlからクラス属性を取得する方法についてでした

<pre class="ruby" name="code">

使用された正規表現は

<pre class="([^"]+)" name="code">

彼らは、代わりに上記のものを使用することを推奨しました

<pre class="(.+)" name="code">

「それは引用を超えているので。」

意味がわかりません。とにかくうまくいくだけですが、最初の正規表現が推奨される理由です。何か不足していますか?教えてください。

前もって感謝します。

4

4 に答える 4

4

.+貪欲にマッチします。たとえば、

<pre class="ruby" size="medium" name="code"> 

一致しruby" size="mediumます。さらに悪いことに、同じ行に 2 つのタグがある場合、タグの境界を越えて一致します。

<pre class="ruby" name="code">foo</pre> <pre class="python" name="code">bar</pre>

結果はruby" name="code">foo</pre> <pre class="python!

したがって、HTML がどのように見えるかを正確に知っている限り、.+動作する可能性がありますが、予想外に変更されるとすぐに (HTML はそうではありません)、正規表現は (2 番目のもののように) 単純に失敗することはありませんが、間違ったものを一致させます。

したがって、2 番目の正規表現の方が安全です (正確に何を照合できるかがより明示されているため)。.+通常は単純なものや「何にでも一致」することを避け、.*代わりに何を一致させたいかを考える必要があります。

とはいえ、まったく同じ理由で、HTML やその他のマークアップ言語を正規表現と一致させようとするべきではありません。そのためのより優れたツールがあるからです。

于 2012-04-08T07:54:42.480 に答える
2

この例を考えてみましょう。

<pre class="scooby" name="not-code">
  content
</pre>

...other HTML...

<pre class="ruby" name="code">
  content
</pre>

この正規表現を使用して[*]:

<pre class="(.+)" name="code">

...最初の部分<pre class="---最初のタグの照合を開始し、次に(.+)ドキュメントの残り全体を消費します。ただし、残りの正規表現---は" name="code">そこで一致できないため、2番目のタグで可能な位置が見つかるまでバックオフします。scooby結果:グループは、からまでのすべてをキャプチャすることになりrubyます。

(.+?)これは、欲張りの代わりに欲張りでないものを使用する場合でも当てはまります(.+)。欲張りでない数量詞は正規表現が可能な限り最短の一致を返す原因になるとよく言われますが、そうではありません。貪欲な正規表現のように、最初の機会にマッチングを開始します。できるだけ早くマッチングを停止します。このような、欲張りでない数量詞が役に立たない状況は珍しいことではありません。

考えるべきもう1つのことは、一致する可能性がない場合です。たとえば、<pre>最初の属性を持つタグはあるがclass="~whatever~"、属性を持つタグはない場合name="code"です。それぞれで、貪欲な人(.+)は文書全体をむさぼり食い、それからそれが開始点に達するまで後退してからあきらめます。欲張りでない人(.+?)は後戻りしませんが、ページ全体をスキャンし、はるかにゆっくりと実行します(" name="code">各位置で効果的に先読みを行います)。

この正規表現で:

<pre class="([^"]+)" name="code">

...タグが一致するかどうかを判断するために、タグの末尾を超えてスキャンする必要はありません。

一致する可能性がない場合はどうなるかを常に考えてください。これはおそらく、正規表現の作成者が行う最も一般的な監視であり、最もパフォーマンスの問題を引き起こすものです。

[*]説明のために、マッチはDOTALLモード(別名シングルラインモード)で実行されていると想定しています。

于 2012-04-08T11:05:50.323 に答える
2

正規表現マッチングは通常、可能な限り長い正規表現とのマッチングを試みます。したがって、"([^"]+)" は、最初に見つかった引用符までしか一致しません一方、"(.+)" は、文字列の最初の引用符から最後の引用符まで一致します。

たとえば、それらを質問に適用した場合、最初の文字列は に一致"ruby"します。これは、質問の最初の引用文字列だからです。2 番目は、質問の最後の引用であるため、"rubyonから までずっと一致します (そして、その間に他のいくつかの引用文字列が含まれます。beyond the quote"

于 2012-04-08T07:54:44.350 に答える
1

クラスを否定することは、通常、一致させたいものについてより具体的であり、壊滅的なバックトラッキングなどの状況から保護するのに役立ちます。

Jeff Atwood は少し前にそれについて興味深いブログ記事(x+x+)+yを書き、そこで彼は一見無害に見える正規表現の例を挙げました。被写体がこのように小さい場合でも: xxxxxxxxxxxxxxxxxxxx.

それを読んでください、それは本当に非常に興味深いものです。

于 2012-04-08T10:52:02.257 に答える