2007年10月30日 20:00 [Edit]

perl - 勝手に添削 - 40行で作るPerl用テンプレートエンジン

camel

久々の勝手に添削。今回はこちら。

正規表現がらみなので、Perl以外でも有用。


添削箇所は、こちら。

40行で作るPerl用テンプレートエンジン
sub convert {
    return unless defined(my $str = shift);
    $str =~ s{&}{&}gso;
    $str =~ s{<}{&lt;}gso;
    $str =~ s{>}{&gt;}gso;
    $str =~ s{\"}{&quot;}gso;
    $str;
}

これの最初のsubstitutionが&amp;ではなくて&ではないかというのはさておき、こういった場合、何度も正規表現をかけて少しずつというのは、効率の面だけではなくバグを呼ぶという点を考えてもいい手とは言えない。

例えば、これを以下のように書いてしまった場合、どうなるだろうか。

sub convert {
    return unless defined(my $str = shift);
    $str =~ s{<}{&lt;}gso;
    $str =~ s{>}{&gt;}gso;
    $str =~ s{\"}{&quot;}gso;
    $str =~ s{&}{&amp;}gso;
    $str;
}

この場合、先に&gt;となったものが、&amp;gt;となるリスクが避けられない。

こういう場合は、文字クラスとhashのコンボで攻めるのが正しい。

my %escaped = ( '&' => 'amp', '<' => 'lt', '>' => 'gt', '"' => 'quot' );
sub escape {
    my $str = shift or return;
    $str =~ s{([&<>"])(?!amp;)}{'&' . $escaped{$1} . ';'}msxgeo;
    $str;
}

将来性を考えると、こうするとさらによさそうだ。

my %escaped = ( '&' => 'amp', '<' => 'lt', '>' => 'gt', '"' => 'quot' );
my $cclass2escape = '[' . join('', keys %escaped) . ']';
sub escape {
    my $str = shift or return;
    $str =~ s{($cclass2escape)(?!amp;)}{'&' . $escaped{$1} . ';'}msxgeo;
    $str;
}

(?!amp;)がいらない、ということであれば、正規表現を使わない方法もある。

my %escaped = ( '&' => 'amp', '<' => 'lt', '>' => 'gt', '"' => 'quot' );
sub escape{
    my $str = shift or return;
    my $result = '';
    $result .= $escaped{$_} ? '&' . $escaped{$_} . ';' : $_
        for (split //, $str);
    $result;
}

もっとも、互換性を考えればCPANのHTML::EntitiesHTML::Entities::encode_entities()を使うべきという意見もあるが、この場合はCPANに頼るのは趣旨に反するだろう。

この問題、Web上で実に多く目にするので、改めて添削した次第。

Dan the Perl Monger

追記:

はてなブックマーク - t-murachiのブックマーク / 2007年10月30日
s/[<>&"]/'&'.{qw(< lt > gt & amp " quot)}->{$&}.';'/eg

惜しい。$&はペナルティが大きいので使用は避けるべき。

s/([<>&"])/'&'.{qw(< lt > gt & amp " quot)}->{$1}.';'/eg;

かな。2bytes長いけど。

0行で作るPerl用テンプレートエンジン : ひろ式めもちょう
テンプレートタグの開始文字列は「@{[ do {」、終了文字列が「} ]}」です。

究極www これだから Perl Mongers という生き物はwww


この記事へのトラックバックURL

この記事へのトラックバック
60行で作るPHP用テンプレートエンジン http://anond.hatelabo.jp/20071030034313 40行で作るPerl用テンプレートエンジン http://anond.hatelabo.jp/20071030153111 404 Blog Not Found:perl - 勝手に添削 - 40行で作るPerl用テンプレートエンジン http://blog.livedoor.jp/da...
0行で作るPerl用テンプレートエンジン【ひろ式めもちょう】at 2007年10月30日 21:54
この記事へのコメント
「$&はペナルティが大きいので使用は避けるべき」のところをご教授いただきたく。
Posted by ぬー at 2007年11月03日 20:37
msxgeoってなんかいいな
Posted by とほりすがり at 2007年10月31日 10:13
ハテナの増田のPHPのテンプレートエンジンに触発されて、
自分でも書いてみようと思ったんですが・・・
0行なんてのが出てしまってたんですね。
やる気を完全に持ってかれました(爆)

Posted by t_ishida at 2007年10月31日 00:58