Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 如何修改传递给子例程引用的标量引用?_Perl_Pass By Reference_Subroutine - Fatal编程技术网

Perl 如何修改传递给子例程引用的标量引用?

Perl 如何修改传递给子例程引用的标量引用?,perl,pass-by-reference,subroutine,Perl,Pass By Reference,Subroutine,我有一个将文档转换为不同格式的函数,然后根据文档类型调用另一个函数。除了需要一些清理的HTML文档之外,其他的一切都非常简单,而且根据清理的来源不同,清理是不同的。因此,我的想法是,我可以将对子例程的引用传递给convert函数,这样调用者就有机会修改HTML,就像这样(我不在工作,所以这不是复制和粘贴): 然后被称为: Converter->new->convert("./whatever.html", sub { s/<html>/<xml>/i });

我有一个将文档转换为不同格式的函数,然后根据文档类型调用另一个函数。除了需要一些清理的HTML文档之外,其他的一切都非常简单,而且根据清理的来源不同,清理是不同的。因此,我的想法是,我可以将对子例程的引用传递给convert函数,这样调用者就有机会修改HTML,就像这样(我不在工作,所以这不是复制和粘贴):

然后被称为:

Converter->new->convert("./whatever.html", sub { s/<html>/<xml>/i });
Converter->new->convert(“./whater.html”,sub{s///i});
我已经尝试了一些不同的方法,但是我不断地得到“在替换中使用未初始化的值(s//)”。有没有办法做我想做的事

谢谢

试试这个:

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

请记住,
s//
本身在
$\uu
上运行,但标量引用作为参数传递到回调子函数中,因此位于
@
数组中

因此,您可以将回调子对象更改为以下内容:

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

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

(只要参数是标量变量而不是文字字符串,这实际上会修改原始字符串。)

如果是我,我会避免修改标量引用,只返回更改后的值:

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);
}
但是,如果您想修改sub的参数,那么在Perl中所有的子参数都是通过引用传递的(sub调用的参数的别名是
@
)。因此,您的转换子项可以如下所示:

sub { $_[0] =~ s/<html>/<xml>/ }
sub _convert_html
{
    my ($self, $filename, $coderef) = @_;

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

    $coderef->() for $html;

    $self->save_to_file($filename, $html);
}
用于的
是正确本地化
$的一种简单方法。您还可以执行以下操作:

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

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

    $coderef->();

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

在阅读以下任何答案之前:您可能希望尝试在每个子例程级别添加一些print语句,以查看作为参数得到的内容是否与您认为应该得到的内容匹配。提示:替换coderef中的print语句应该会引导您找到答案。感谢您的详细解释:-)这需要大量复制:首先复制到参数堆栈上,然后更改它,然后复制回参数堆栈。如果你必须处理很多很多页面,这可能会造成伤害。请注意,如果速度很重要,
local
for
快,只有一个项目。请注意,如果你注意到local和for之间的速度差,你就犯了其他错误。此外,Sub::AliasedUnderscore是一种比local或for更干净的方法。对于映射代码示例,我想知道我希望返回值是什么。:)@布莱恩:真的;通常我会编写一个转换子函数来返回新值,而不是使用引用。
sub { $_[0] =~ s/<html>/<xml>/ }
sub _convert_html
{
    my ($self, $filename, $coderef) = @_;

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

    $coderef->() for $html;

    $self->save_to_file($filename, $html);
}
sub _convert_html
{
    my ($self, $filename, $coderef) = @_;

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

    $coderef->();

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