Perl覚え書き20041124

 また今日もある企業のGateKeeperからのアクセスがあった。普通に「どんなんかな?」って見に来る分には全然かまわないんだけど、なんかそうでもなさそうで気味が悪い。

 さて、今回紹介する部分で一応は、たとえばHTMLをファイルから読み込んで許可されたタグ、属性だけを残して表示すると言うような事が可能になる。

 とは言っても解説する部分はほとんどない。その前に前回の日記の変更点。80行目を次のように変更する。

80: 	$str =~ s|[^a-zA-Z0-9/!]||g if $str !~ /!--/;

 では今回の部分。

 1: $tag_regex_ = q{[^"'<>]*(?:"[^"]*"[^"'<>]*|'[^']*'[^"'<>]*)*(?:>|(?=<)|$(?!\n))}; #'}}}}
 2: $comment_tag_regex =
 3:     '<!(?:--[^-]*-(?:[^-]+-)*?-(?:[^>-]*(?:-[^>-]+)*?)??)*(?:>|$(?!\n)|--.*$)';
 4: $tag_regex = qq{$comment_tag_regex|<$tag_regex_};
 5: 
 6: open(FH,"sample.html") or die "cannot open file:$!";
 7: {
 8: 	local $/;
 9: 	$html = <FH>;
10: }
11: 
12: my($prematch,$match);
13: 
14: while($html =~ /$tag_regex/) {
15: 	$prematch = $`;
16: 	$match = $&;
17: 	$html = $';
18: 	print $prematch;
19: 	print ${parse_print(\$match)};
20: }

 今回の最大ポイントは正規表現。というかそれ以外には…。ちなみにこの正規表現Perlメモの目次から正規表現−>HTMLタグの正規表現と辿ったところに載っている物だ。色々解説が載っているが、はっきり言って何がどうなってこういう正規表現になるのかは全く理解していない。

 この正規表現で順番に回していくだけだ。

 あと一つ、多少変わったことをしてる部分は7〜10行。そこそこ有名な話の様だけど、local $/;とすることで改行を含んだファイルを一気に読み込める。undef $/;とするのはあまりにも有名な話だが、それだと$/を元に戻さないといけないため、ブロックで囲んでlocal宣言しているのがポイント。localとmyでは効果が違うため、ここはlocalでなくてはならない。

 ついでだからlocalとmyとの簡単な説明。

 localは指定された変数に一時的に別の値を与える。ブロック内で宣言された部分から、そのブロックが終わるまで有効。ブロック内のブロックや関数内でもその数値は有効となる。

 一方myはPerl5から使えるようになった物で、これが本当のローカル宣言と言える。有効範囲は宣言された部分からブロックが終わるまでだが、その中にあるブロックや関数では無効というか、別の物として扱われる。これはmyでは変数を格納する場所が新たに作られているからだ。

 次のサンプルプログラム。

 1: print "local\n";
 2: &local_test;
 3: print "my\n";
 4: &my_test;
 5: exit;
 6: 
 7: sub local_test {
 8: 	local $a = 1;
 9: 	print "$a\n";
10: 	&overwrite;
11: 	print "$a\n";
12: }
13: 
14: sub my_test {
15: 	my $a = 1;
16: 	print "$a\n";
17: 	&overwrite;
18: 	print "$a\n";
19: }
20: 
21: sub overwrite {
22: 	$a = 2;
23: }

 これを実行すると、以下のような結果が得られる。

local
1
2
my
1
1

 Perl5であれば、上記のlocal $/;の様に特別な理由が無い限り、myを使用することが推奨されている。myの方が高速で安全だからだ。localだと上のサンプルのように、意図しない部分で変数が書き換えられてしまう可能性があるという理由。

 と言うわけで今日は終了。