如何验证 Perl 中的函数参数?
How can I validate function parameters in Perl?
能否请您告诉我在 Perl 中什么是验证函数参数最聪明的方法?
代码片段:
sub testfunction {
my ($args) = @_;
my $value = $args->{value} || die "no value set";
# process value ...
}
testfunction({value => 'Hallo'});
testfunction({novalue => 'Hallo'});
以上方法是在 perl 中验证函数参数的一个很好的替代方法还是有更聪明的方法?
非常感谢大家。
这个问题:
$args->{value} || die "no value set";
是否定义了值但设置为零时会失败。
testfunction({value => 0}); #Oops!
如果值不允许为零,那可能没问题。但一般来说,更好的设计是使用 exists
或 //
检查哈希键是否已定义。
die "Value not defined!" if not exists $args->{value};
die "Value not defined!" unless exists $args->{value};
$args->{value} // die "Value not defined!";
对于这个简单的语句,我倾向于选择 exists
,因为我认为它读起来更清楚一些。但是 //
允许一些不错的事情,比如替换默认值,如 Sobrique 的回答所示。我也同意 Sobrique 关于方法的更一般性建议。
这在很大程度上取决于您要完成的任务,以及它是用户输入、本地函数还是远程函数。
我的意思是,一些参数 - 'validate' 尝试使用它要容易得多。例如一个文件名 - 与其尝试手动捕获所有边缘情况,不如将其传递给 open .... or die $!
有时 - 'default-and-override' 更明智。例如:
my ( $first_thing, $second_thing ) = @_;
$first_thing //= "default value";
$second_thing //= 0;
注意 - 使用 //
而不是 ||
- 它在用法上 相似 ,但它只是测试未定义 - 而不是被定义 - but-false,例如 ''
或 0
。
有时您希望通过应用一组验证正则表达式进行更好的验证。请注意,有些东西(例如电子邮件地址或 IP 地址)可能比您想象的要复杂得多,无法彻底验证 - 因此 'was there a parameter at all' 的简单边缘情况可以工作。
当然,到时候你也可以开始看function prototypes。这与您可能从其他语言中想到的原型制作完全不同:
#!/usr/bin/env perl
#says - must have a single scalar arg.
sub testfunction($) {
my ( $required_arg ) = @_;
print $required_arg;
}
testfunction(1);
testfunction;
后者将失败:
Not enough arguments for main::testfunction
注意 - perl 原型检查参数的 type 和 number(例如,它是标量还是数组)。但是不要检查值,并且 can 在传入数组时会产生一些稍微出乎意料的效果。
我建议传递哈希值非常适合默认机制,因为您可以:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my %defaults = (
"test" => 1,
);
sub with_default {
my %args = (%defaults, @_);
print Dumper \%args;
}
with_default;
with_default(test => 4 );
但是回到你原来的情况 - 如果你的函数在没有设置 'value' 的情况下根本无法工作,那么最好在代码中拼写出来:
if ( not defined $args -> {value}
or not $args -> {value} =~ m/^\w+$/ ) {
die 'value parameter must be supplied and match m/^\w+$/';
}
此时可能值得一提的是 'taint' 模式。这是 perl
的一项功能,您在许多其他语言中都看不到。
它明确告诉解释器 'user supplied' 是 'tainted',因此 不能 未经验证就使用。这包括不安全的路径、环境变量等。
但是:
#!/usr/bin/env perl -T
use strict;
use warnings;
system "echo $ENV{'USERNAME'}";
将失败 - 因为 system
不允许 'tainted' 变量。 (但是 print
会)。在删除 'taint' 之前,您需要通过验证步骤(例如,通常是正则表达式)来传递它。
能否请您告诉我在 Perl 中什么是验证函数参数最聪明的方法?
代码片段:
sub testfunction {
my ($args) = @_;
my $value = $args->{value} || die "no value set";
# process value ...
}
testfunction({value => 'Hallo'});
testfunction({novalue => 'Hallo'});
以上方法是在 perl 中验证函数参数的一个很好的替代方法还是有更聪明的方法? 非常感谢大家。
这个问题:
$args->{value} || die "no value set";
是否定义了值但设置为零时会失败。
testfunction({value => 0}); #Oops!
如果值不允许为零,那可能没问题。但一般来说,更好的设计是使用 exists
或 //
检查哈希键是否已定义。
die "Value not defined!" if not exists $args->{value};
die "Value not defined!" unless exists $args->{value};
$args->{value} // die "Value not defined!";
对于这个简单的语句,我倾向于选择 exists
,因为我认为它读起来更清楚一些。但是 //
允许一些不错的事情,比如替换默认值,如 Sobrique 的回答所示。我也同意 Sobrique 关于方法的更一般性建议。
这在很大程度上取决于您要完成的任务,以及它是用户输入、本地函数还是远程函数。
我的意思是,一些参数 - 'validate' 尝试使用它要容易得多。例如一个文件名 - 与其尝试手动捕获所有边缘情况,不如将其传递给 open .... or die $!
有时 - 'default-and-override' 更明智。例如:
my ( $first_thing, $second_thing ) = @_;
$first_thing //= "default value";
$second_thing //= 0;
注意 - 使用 //
而不是 ||
- 它在用法上 相似 ,但它只是测试未定义 - 而不是被定义 - but-false,例如 ''
或 0
。
有时您希望通过应用一组验证正则表达式进行更好的验证。请注意,有些东西(例如电子邮件地址或 IP 地址)可能比您想象的要复杂得多,无法彻底验证 - 因此 'was there a parameter at all' 的简单边缘情况可以工作。
当然,到时候你也可以开始看function prototypes。这与您可能从其他语言中想到的原型制作完全不同:
#!/usr/bin/env perl
#says - must have a single scalar arg.
sub testfunction($) {
my ( $required_arg ) = @_;
print $required_arg;
}
testfunction(1);
testfunction;
后者将失败:
Not enough arguments for main::testfunction
注意 - perl 原型检查参数的 type 和 number(例如,它是标量还是数组)。但是不要检查值,并且 can 在传入数组时会产生一些稍微出乎意料的效果。
我建议传递哈希值非常适合默认机制,因为您可以:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my %defaults = (
"test" => 1,
);
sub with_default {
my %args = (%defaults, @_);
print Dumper \%args;
}
with_default;
with_default(test => 4 );
但是回到你原来的情况 - 如果你的函数在没有设置 'value' 的情况下根本无法工作,那么最好在代码中拼写出来:
if ( not defined $args -> {value}
or not $args -> {value} =~ m/^\w+$/ ) {
die 'value parameter must be supplied and match m/^\w+$/';
}
此时可能值得一提的是 'taint' 模式。这是 perl
的一项功能,您在许多其他语言中都看不到。
它明确告诉解释器 'user supplied' 是 'tainted',因此 不能 未经验证就使用。这包括不安全的路径、环境变量等。
但是:
#!/usr/bin/env perl -T
use strict;
use warnings;
system "echo $ENV{'USERNAME'}";
将失败 - 因为 system
不允许 'tainted' 变量。 (但是 print
会)。在删除 'taint' 之前,您需要通过验证步骤(例如,通常是正则表达式)来传递它。