4

ドキュメントをさまざまな形式に変換する関数があり、ドキュメントの種類に基づいて別の関数を呼び出します。少しのクリーンアップが必要な HTML ドキュメントを除けば、それはすべて非常に簡単です。クリーンアップは、それがどこから来たのかによって異なります。そこで、サブルーチンへの参照を convert 関数に渡して、呼び出し元が HTML を変更できるようにすることを考えました (私は仕事をしていないので、これはコピー アンド ペーストではありません)。 :

package Converter;
...
sub convert
{
    my ($self, $filename, $coderef) = @_;

    if ($filename =~ /html?$/i) {
        $self->_convert_html($filename, $coderef);
    }
}

sub _convert_html
{
    my ($self, $filename, $coderef) = @_;

    my $html = $self->slurp($filename);
    $coderef->(\$html); #this modifies the html
    $self->save_to_file($filename, $html);
}

その後、次のように呼び出されます。

Converter->new->convert("./whatever.html", sub { s/<html>/<xml>/i });

これらの行に沿っていくつかの異なることを試しましたが、「置換での初期化されていない値の使用 (s///)」が引き続き発生します。私がやろうとしていることをする方法はありますか?

ありがとう

4

3 に答える 3

5

私だったら、スカラー ref を変更せずに、変更された値を返すだけです。

sub _convert_html
{
    my ($self, $filename, $coderef) = @_;

    my $html = $self->slurp($filename);
    $html = $coderef->( $html ); #this modifies the html
    $self->save_to_file($filename, $html);
}

しかし、サブルーチンの引数を変更したい場合、Perl ではすべてのサブ引数が参照渡しであることを知っておく価値があります (の要素は@_サブ呼び出しの引数にエイリアスされます)。したがって、変換サブルーチンは次のようになります。

sub { $_[0] =~ s/<html>/<xml>/ }

しかし$_、目的のコード例のように、本当に を操作したい場合は、次のようにする必要があります_convert_html()

sub _convert_html
{
    my ($self, $filename, $coderef) = @_;

    my $html = $self->slurp($filename);

    $coderef->() for $html;

    $self->save_to_file($filename, $html);
}

forを適切にローカライズする簡単な方法です$_。次のこともできます。

sub _convert_html
{
    my ($self, $filename, $coderef) = @_;

    local $_ = $self->slurp($filename);

    $coderef->();

    $self->save_to_file($filename, $_);
}
于 2010-05-17T23:15:11.717 に答える
3

それs///自体はで動作し$_ますが、スカラー参照は引数としてコールバックサブに渡されているため、@_配列内にあることに注意してください。

したがって、コールバックサブを次のように変更できます。

sub { my ( $ref ) = @_; $$ref =~ s/<html>/<xml>/i }

または、Perlサブルーチン引数のエイリアスの性質を利用して、直接変更することもできます。

sub _convert_html { 
    ...
    $coderef->( $html );
}

その後

sub { $_[0] =~ s/<html>/<xml>/i }

(引数がリテラル文字列ではなくスカラー変数である限り、これは実際には元の文字列を変更します。)

于 2010-05-17T23:11:26.877 に答える
2

これを試して:

Converter->new->convert("./whatever.html", sub { ${$_[0]} =~ s/<html>/<xml>/i; });

置換には操作対象が何も与えられていないため、初期化されていない値の警告が表示されます($_スコープで定義されていません)。その値をどこで見つけるかを指示する必要があります(@_参照として、で)。

ファンシーになりたい場合は、デフォルトでcoderefをそのすべての引数で動作させることができます。

sub { map { $$_ =~ s/<html>/<xml>/i } @_ }
于 2010-05-17T23:10:27.283 に答える