Perl-如何使用子例程修改变量而不返回
下一个代码用于获取文件路径并检查是否存在以及是否可以读取;否则,该值将切换为自定义值:Perl-如何使用子例程修改变量而不返回,perl,scope,subroutine,Perl,Scope,Subroutine,下一个代码用于获取文件路径并检查是否存在以及是否可以读取;否则,该值将切换为自定义值: use strict; use warnings; [...] sub checkFilePath{ my ($args) = @_; my $checkingPath = $args->{path}; my $checkingCustomPath = $args->{customPath}; my $canBeRead = 1; if ($chec
use strict;
use warnings;
[...]
sub checkFilePath{
my ($args) = @_;
my $checkingPath = $args->{path};
my $checkingCustomPath = $args->{customPath};
my $canBeRead = 1;
if ($checkingPath) {
if (!(-e "$checkingPath")) {
print "[WARN] File $checkingPath doesn't exist.\n";
$canBeRead = 0;
} elsif (!(-f "$checkingPath")) {
print "[WARN] $checkingPath is not a file.\n";
$canBeRead = 0;
} elsif (!(-r "$checkingPath")) {
print "[WARN] File $checkingPath can't be read.\n";
$canBeRead = 0;
}
}
if (!($canBeRead)) {
# Testing custom regex file path
# If doesn't exist, it will try to use custom file or the script will die
die "[ERR] Custom file $checkingCustomPath doesn't exist\n" if (!(-e $checkingCustomPath));
die "[ERR] Custom file $checkingCustomPath is not a file\n" if (!(-f $checkingCustomPath));
die "[ERR] Custom file $checkingCustomPath cannot be read\n" if (!(-r $checkingCustomPath));
return $checkingCustomPath;
}
return $checkingPath;
}
[...]
$logPath = checkFilePath({
path => $logPath,
customPath => $customLogPath
});
我想知道是否有一种方法可以修改此代码,仅通过一个子程序调用来更新$logPath
,如:
# $logPath = '/tmp/thisfiledoesntexist.txt'
checkFilePath({
path => $logPath,
customPath => $customLogPath
});
# $logPath now has a valid filepath, which is the same as $customLogPath
如果将
$logPath
作为参数(或通过引用)传递给子例程,则可以更改它(通过修改@
的正确元素(或修改引用的标量))。但您将其值复制到一个散列中,并传递对该散列的引用。充其量,您可以修改$hash->{path}
,而不是$logPath
sub fixFilePath {
our $checkingPath; local *checkingPath = \shift; # my \$checkingPath = \shift;
my %args = @_;
my $checkingCustomPath = $args{customPath};
...
return if $canBeRead;
...
$checkingPath = $checkingCustomPath;
}
fixFilePath($logPath,
customPath => $customLogPath,
);
再仔细考虑一下,我决定提出一种不同的、不那么重复的、更清晰的方法:
use strict;
use warnings;
use autouse Carp => qw(croak);
print chooseFilePath('doesnot.exist', "$ENV{TEMP}/t.log"), "\n";
sub chooseFilePath {
my $wantedPath = shift;
my $defaultPath = shift;
if (defined(my $reason = isBadFilePath($wantedPath))) {
warn "[WARN] $reason.\n";
if (defined($reason = isBadFilePath($defaultPath))) {
die "[ERR] $reason.\n";
}
return $defaultPath;
}
return $wantedPath;
}
sub isBadFilePath {
@_ or croak 'Need a path';
my $path = shift;
-e $path or return "File '$path' doesn't exist";
-f _ or return "'$path' is not a file";
-r _ or return "File '$path' can't be read";
return;
}
输出:
C:\…\Temp>perl s.pl
[警告]文件“不存在。存在”不存在。
[错误]文件“C:\…\Temp/t.log”不存在。
C:\…\Temp>echo x>t.log
C:\…\Temp>perl s.pl
[警告]文件“不存在。存在”不存在。
C:\…\Temp/t.log
我不明白为什么这个答案被否决了,所以,+1来自我。我试图修改子例程末尾的$hash->{path}
,但是当它结束时customLogPath
没有改变。我编码的行是{args->{customPath}='Testing';
。在子例程的内部和外部进行打印时,我得到不同的值“我试图在子例程的末尾修改$hash->{path}
”,始终使用使用strict;
!!$hash
不存在。Re“我编码的行是{args->{customPath}”='Testing';
,(我假设你的意思是$args->{customPath}='Testing';
)总是使用使用严格;
!!$args
不存在。是的,我总是在我的脚本上使用严格;
。{args
是一个打字错误。我说的是$args
,它存在于我原来的子例程(中($args)=@;
)。这就是为什么我得到不同的值,我不明白为什么