我有以下代码,我写了截断大值。
sub truncate_large_email_tag
{
my($email_tag) = @_;
my $size = length($email_tag);
if ($size>5000) {
my $fragment = substr($email_tag,0,5000);
$email_tag = $fragment;
#log_it( "\n\Truncated Large Email tags\n\n") if $TRACE;
}
我正在调用这个子程序,使用另一个子程序中的调用说
sub do_something
{
#some code here # CFG_PASS is a hash
$EMAIL{$tag}=$CFG_PASS{$typ}{$tag}{$where . '_DEFAULTS'}; #Email
#tag initialized here
truncate_large_email_tag($EMAIL{$tag});
}
但是当我检查$ EMAIL {$ tag}时仍然指向非截断值。我做错了什么?
答案 0 :(得分:6)
Perl总是通过引用传递。问题是你没有修改参数,而是修改了你在函数中创建并在其中复制参数的变量(my ($email_tag) = @_;
)。
更改
my $fragment = substr($email_tag, 0, 5000);
$email_tag = $fragment;
到
my $fragment = substr($email_tag, 0, 5000);
$_[0] = $fragment;
或
$_[0] = substr($email_tag, 0, 5000);
或
$_[0] = substr($_[0], 0, 5000);
或
substr($_[0], 5000) = '';
所以你最终得到了
sub truncate_inplace {
substr($_[0], $_[1]) = ''
if length($_[0]) > $_[1];
}
truncate_inplace($EMAIL{$tag}, 5000);
但为什么不使用
sub truncate {
my ($s, $max_len) = @_
return length($s) > $max_len ? substr($s, 0, $max_len) : $s;
}
$EMAIL{$tag} = truncate($EMAIL{$tag}, 5000);
答案 1 :(得分:2)
正如您所推测的那样,您正在按值传递$EMAIL{$tag}
,因此您的修改会在子结束后丢失并且原始文件保持不变。有两种方法可以做你想做的事。
方式一:
truncate_large_email_tag(\$EMAIL{$tag});
这将对$EMAIL{$tag}
的引用传递给子例程。在sub中,你需要取消引用它来完成你的工作:
my ( $email_tag_ref ) = @_;
my $email_tag = $$email_tag_ref;
可以缩写为:
my $email_tag = ${ $_[0] };
方式二:
利用@_
特殊且别名调用参数这一事实。
$_[0] = substr($email_tag,0,5000);
通过直接分配到$_[0]
,您将更改原始参数。
就个人而言,我更喜欢方式,因为它更明确。
答案 2 :(得分:1)
在perl中,标量参数会自动通过引用传递,这就是你在这里所拥有的。你不是想传递整个哈希;你只是想修改其中的一个值。
您可以通过分配回@_
来修改子程序调用的参数,如下所示:
sub truncate_large_email_tag
{
my($email_tag) = @_;
my $size = length($email_tag);
if ($size>5000) {
my $fragment = substr($email_tag,0,5000);
$email_tag = $fragment;
#log_it( "\n\Truncated Large Email tags\n\n") if $TRACE;
}
$_[0] = $email_tag; # modify argument in the caller
}
那就是说, 通常更清楚地发送一个明确的引用。为此,在调用时在参数前面加一个反斜杠,并在被调用者中使用额外的$
取消引用:
sub truncate_large_email_tag
{
my ($email_tag_ref) = @_;
my $size = length($email_tag);
if ($size>5000) {
my $fragment = substr($email_tag,0,5000);
$$email_tag_ref = $fragment;
#log_it( "\n\Truncated Large Email tags\n\n") if $TRACE;
}
}
然后当你打电话时:
truncate_large_email_tag(\$EMAIL{$tag})