Perl覚え書き20041206
うーん…だったらどんな回答なら納得するんだろうか。その模範回答ってのを見せて欲しいな。これは単なる独り言。
今回は短い。非常に短い。なんたって32行目の下に次の行を追加するだけ。
$ignore = 1 if !$ignore and grep !/^(["']).*\1$|^[^"']/,@eles;
これは何をしているかというと、まあ if !$ignore は既に無視フラグが立っていたら無駄な処理をしないようにするためで本編は and 以降。grep 関数を使って、要素の先頭が " か '(以下クオート文字)で始まっているにも関わらず行末がクオート文字で終わっていない物を抜き出している。
ブラウザでの解釈で、文字列がクオート文字で始まっているのに閉じるクオート文字が見あたらない時は次に > が出てきたところでその「タグらしき物」が終わったとし、さらにその「タグらしき物」を単なる文字列として処理してしまう。つまり、画面上にその「タグらしき物」そのものがそのまま表示される。
ということで、まあブラウザがそう解釈するんだから別に不許可タグ扱いしなくてもいいのかもしれないけど、まあその方がわかりやすいかと思って。
で、この部分の正規表現は最初は次のように書いていた。
/^(["']).*[^\1]$/
先頭がクオート文字で始まっていて、行末は先頭と同じではない物、という意味で書いた。だけどこれでは動かなかった。\1 の部分が単なる 1 になってしまっているのかと思ってマッチさせる文字の最後を 1 にしてみたが変化は無し。そういう問題ではないようだ。
(?!\1)
にしても変わらないし
(?{ "[^$1]" })
でもダメだった。
(?{ print "[^$1]" })
って書いたら、たとえば先頭が " ならちゃんと [^"] と表示されているのに…。この書き方の意味を取り違えてるんだろうか? { } で囲った物でその部分が置き換えられるんじゃなかったのか。
まあ仕方がないから最初に書いた正規表現に落ち着いた。「先頭がクオート文字で終端が同じクオート文字ではないもの」というのは、逆に言うと「先頭がクオート文字で終端も同じクオート文字、もしくは先頭がクオート文字では無い物」には当てはまらない物ということになる。
先頭がクオート文字ではなくて終端がクオート文字の場合は値の解釈がおかしくなるだけでタグとして認識はしているから放っておく。たとえば color="red" と color=red" では色が違う。どういう解釈をしているのかまでは知らないが…。
余談になるが、実を言うと最初から grep を使っていたわけではない。最初に書いたのは次の通り。
unless($ignore) { foreach $qcheck (@eles) { if($qcheck =~ /^(["'])/) { if($qcheck !~ /$1$/) { $ignore = 1; last; } } } }
昨日のソースで $qcheck が宣言されていてコメントアウトしてあったのはこれを作りかけていたから。まあ正規表現を二回使ってるからここはさっきの grep に渡した正規表現に置き換えられるが、まあだいたいこんな所。
これでも当然動く。が、速度的にはどうなんだろう。grep 関数で配列を一気にどばっと処理してしまう方が速いような気もするし、このループの方が、もし途中で正規表現にマッチする要素が現れた場合はそこでループを抜けられるため速く終わる可能性がある。
ベンチマークを取ってみればいいのかもしれないが、その取り方が分からない。確かベンチマークを取るモジュールがあったような…。
ベンチマークと言えばもう一つ気になるのがタグにマッチする正規表現。前に使っていた物と今の物とどれくらい違うのか。構造上、以前の物に戻すわけにはいかないけど、差が出る物なのか、出るとすればそれはどれぐらい違うのか、というのはちょっと気になる。
まあけっこう大きな文字列を食わせないと差は出ないかも知れないけど。