如何在Perl中验证函数参数?

时间:2017-05-19 09:01:38

标签: function perl validation function-parameter

请告诉我Perl中哪些是验证函数参数的最明智的方法?

代码段

sub testfunction {
    my ($args) = @_;
    my $value = $args->{value} || die "no value set";
    # process value ...
}


testfunction({value => 'Hallo'});

testfunction({novalue => 'Hallo'});

以上方式是验证perl中的函数参数的好方法还是有更聪明的方法? 非常感谢大家。

2 个答案:

答案 0 :(得分:10)

这很大程度上取决于您尝试完成的内容,以及它的用户输入,本地功能还是远程功能。

我的意思是,一些参数 - 它更容易验证'通过尝试使用它。例如文件名 - 而不是试图手动捕获所有边缘情况,只需将其传递给open .... or die $!

有时候 - 默认 - 覆盖'更明智。 E.g:

my ( $first_thing, $second_thing ) = @_; 
$first_thing //= "default value";
$second_thing //= 0; 

注意 - 在使用中使用//而不是|| - 它的类似的,但它只测试未定义 - 而不是被定义 - 但是 - 例如''0

有时您希望通过应用一组验证正则表达式来更好地进行验证。只是要小心,有些东西 - 比如电子邮件地址或IP地址 - 可能比你想象的要彻底验证要复杂得多 - 所以一个简单的边缘情况是'是否有参数?可以工作。

当然,此时您也可以开始查看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原型检查参数的类型 number (例如它是标量,是数组)。但是,不要检查值,并且可以在传入数组时有一些意想不到的效果。

我建议传入哈希非常适合默认机制,因为你可以:

#!/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 );

但是要回到原来的情况 - 如果你的功能只是在没有“价值”的情况下工作了。如果设置好了,那么在代码中拼出它是件好事:

if ( not defined $args -> {value} 
  or not $args -> {value} =~ m/^\w+$/ ) {
   die 'value parameter must be supplied and match m/^\w+$/';
}

可能值得一提的是'污染'此时的模式。它是您在许多其他语言中看不到的perl的功能。

它具体告诉口译员“用户提供了”'被污染的'因此不能在没有验证的情况下使用。这包括不安全的路径,环境变量等。

请参阅perlsec

可是:

#!/usr/bin/env perl -T
use strict;
use warnings;

system "echo $ENV{'USERNAME'}";

会失败 - 因为system不会允许' tainted'瓦尔。 (但print会)。您需要在“污点”之前通过验证步骤(例如正则表达式)。已移除。

答案 1 :(得分:3)

这个问题:

$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关于方法的更一般的建议。