如何修改传递给子例程引用的标量引用?
我有一个将文档转换为不同格式的函数,然后根据类型文档调用另一个函数。除了需要进行一些清理的 HTML 文档之外,其他所有内容都非常简单,而且清理工作根据其来源而有所不同。所以我有一个想法,我可以将对子例程的引用传递给转换函数,以便调用者有机会修改 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///)”。有什么办法可以做我想做的事情吗?
谢谢
I have a function to convert documents into different formats, which then calls another function based on the type document. It's pretty straight forward for everything aside from HTML documents which require a bit of cleaning up, and that cleaning up is different based on where it's come from. So I had the idea that I could pass a reference to a subroutine to the convert function so the caller has the opportunity to modify the HTML, kinda like so (I'm not at work so this isn't copy-and-pasted):
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);
}
which is then called by:
Converter->new->convert("./whatever.html", sub { s/<html>/<xml>/i });
I've tried a couple of different things along these lines but I keep on getting 'Use of uninitialized value in substitution (s///)'. Is there any way of doing what I'm trying to do?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果是我,我会避免修改标量引用而只返回更改后的值:
但是,如果您想修改子参数,则值得知道所有子参数在 Perl 中都是按引用传递的(
@_
是子调用参数的别名)。所以你的转换子可以看起来像:但是如果你真的想对
$_
进行操作,就像你想要的代码示例中那样,你需要使_convert_html()
看起来例如:for
是正确本地化$_
的简单方法。您还可以这样做:If it were me, I would avoid modifying the scalar ref and just return the changed value:
However, if you want to modify a sub's arguments, it is worth knowing that all sub arguments are pass-by-reference in Perl (the elements of
@_
are aliased to the arguments of the sub call). So your conversion sub can look like:But if you really want to operate on
$_
, like you have in your desired code example, you need to make_convert_html()
look like:The
for
is an easy way to properly localize$_
. You can also do:请记住,
s///
本身对$_
进行操作,但是您的标量引用将作为参数传递到您的回调子中,因此位于>@_
数组。因此,您可以将回调 sub 更改为如下所示:
或者,您可以利用 Perl 子例程参数的别名性质,并直接修改它:
然后
(这实际上会修改原始字符串,只要参数是标量变量而不是文字字符串。)
Remember that an
s///
by itself operates on$_
, but your scalar reference is being passed into your callback sub as an argument, and is therefore in the@_
array.So you can just change your callback sub to something like this:
Or, you could take advantage of the aliased nature of Perl subroutine arguments, and modify it directly:
and then
(This will actually modify the original string, as long as the argument is a scalar variable and not a literal string.)
试试这个:
您收到未初始化值警告,因为没有为替换提供任何可操作的内容(
$_
在其范围内未定义)。您需要告诉它在哪里可以找到它的值(在@_
中,作为参考)。如果你想变得更奇特,你可以让 coderef 默认对其所有参数进行操作:
Try this:
You are getting an uninitialized value warning because the substitution isn't being given anything to operate on (
$_
is undefined in its scope). You need to tell it where to find its value (in@_
, as a reference).If you want to be fancy you could make the coderef operate on all its args by default: