*
一般にワイルドカードとして知られているメタキャラクタです。
<a\s*</a>
のようにして使います。
どんな文字列でも消費するので使い勝手が良いと思われがちですが、これがなかなか使いどころが難しいメタキャラクタです。
*
は細心の注意を払って、使用して下さい。
*
は最長マッチではないかといわれることが良くありますが、これはユーザーが勘違いしている可能性が高いと思っています。
例えば、<a\s*>
の *
は後ろにある >
を見ているので、このパターンだけを見れば <a\s[^>]+>
と同義です。
ところが、<a\s*>
の後ろに違う文字が1つでもあると、違った意味を持つようになります。
次のようなフィルタを考えてみて下さい。
[Patterns] Name = "Kill ad image" Active = TRUE Limit = 256 Match = "<a\s*><img[^>]++alt=$AV(ad image)[^>]+></a>"htmlソース1
<a
href=
"..."
>
<img
src=
"..."
alt="ad image"
>
</a>
alt属性値に "ad image" を持つ画像をa要素を含めて消すフィルタです。綺麗に消えてくれますね。
htmlソース1 では上手くいきましたが、これは誤爆する要因を孕んでいます。
例えば、以下のhtmlソースです。
<a
href=
"..."
>
</a>
<a
href=
"..."
>
<img
src=
"..."
alt="ad image"
>
</a>
Kill ad image は htmlソース2 の最初から最後までの全てを消し去ります。
これは *
が後ろの 文字列 を見るからです。
<a\s*>
に使い慣れると *
が直後の文字 >
だけを見ているように思えてくる事もあると思いますが、これは誤りです。
(実際に、私も勘違いした経験があります。)
Kill ad image の場合、*
は ><img[^>]++alt=$AV(ad image)[^>]+></a>
まで見ています。
従って、<a\s
で始まり、><img[^>]++alt=$AV(ad image)[^>]+></a>
で終わる文字列であればマッチしてしまうのです。
*
の後ろに1文字だけあるのであれば誤爆する事はありません。
が、つい癖で後ろに文字列が来る場合にも *
を使ってしまう事はあり得ると思います。(人はミスをする生きものですから)
そのような人為的ミスを防ぐためにも、後ろに1文字が来るときには [^>]+
のように文字クラスを使う癖を付けておく事をお勧めします。
次のようなフィルタを考えてみてください。
フィルタ[Patterns] Name = "Replace prx" Active = TRUE Limit = 256 Match = "(<div\sclass=$AV(msg)>*<strong>)\0prx(</strong>*</div>)\1" Replace = "\0Proxomitron\1"htmlソース1
<div
class=
'msg'
>
...<strong>
prx</strong>
...</div>
「* は最短マッチ, 最長マッチ?」で説明したように、このフィルタは誤爆する可能性があります。
この場合に、有効な解決法は$NESTで検索範囲を制限することです。
これなら、初めに$NESTで
の範囲に制限するので、<div
class=
'msg'
>
...</div>
*
がdiv要素を乗り越えて消費する心配がありません。
$NEST, $URL などの制限された領域で、*
を使うのは賢い方法です。