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

Fra*_*345 2 validation perl function function-parameter

你能告诉我Perl中哪些是验证功能参数最聪明的方法吗?

代码片段:

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


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

testfunction({novalue => 'Hallo'});
Run Code Online (Sandbox Code Playgroud)

以上方式是在perl中验证函数参数的一个很好的替代方法还是有更聪明的方法?非常感谢大家.

Sob*_*que 10

这很大程度上取决于您要完成的任务,以及它是用户输入,本地功能还是远程功能.

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

有时候 - '默认 - 覆盖'更明智.例如:

my ( $first_thing, $second_thing ) = @_; 
$first_thing //= "default value";
$second_thing //= 0; 
Run Code Online (Sandbox Code Playgroud)

注意 - 使用//而不是||- 它在使用方面类似,但它只测试未定义 - 而不是被定义 - 但是 - 例如''或者0.

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

当然,此时您还可以开始查看函数原型.这与您从其他语言中可能想到的原型不同:

#!/usr/bin/env perl

#says - must have a single scalar arg. 
sub testfunction($) {
   my ( $required_arg ) = @_; 
   print $required_arg;
}

testfunction(1);
testfunction;
Run Code Online (Sandbox Code Playgroud)

后者将失败:

Not enough arguments for main::testfunction
Run Code Online (Sandbox Code Playgroud)

注意 - perl原型检查参数的类型数量(例如它是标量,是数组).但是不要检查值,并且在传入数组时产生一些意想不到的影响.

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

#!/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 );
Run Code Online (Sandbox Code Playgroud)

但是回到原来的情况 - 如果你的函数在没有设置'value'的情况下根本不起作用,那么在代码中拼出它是很好的:

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

在这一点上,可能值得提一下"污点"模式.这perl是你在许多其他语言中看不到的一个特征.

它特别告诉解释器"用户提供的"是"污染的",因此无法在没有验证的情况下使用.这包括不安全的路径,环境变量等.

perlsec

但:

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

system "echo $ENV{'USERNAME'}";
Run Code Online (Sandbox Code Playgroud)

将失败 - 因为system不会允许'污染'变量.(但print愿意).在删除"污点"之前,您需要通过验证步骤(例如通常使用正则表达式).

  • 您可能希望在`die'值参数中使用单引号而不是双引号...匹配/ ^\w + $ /"`与双引号一样,`$ /`将被解释为Perl变量. (2认同)