如何在Perl中检查多个变量是否为空

如何在Perl中检查多个变量是否为空,perl,variables,Perl,Variables,我有一个Perl脚本,在脚本继续之前必须初始化变量。一个冗长的if语句,我在其中检查每个变量,这是显而易见的选择。但也许有一种更优雅或简洁的方法来检查几个变量 编辑: 我不需要检查“defined”,它们总是用空字符串定义的,我需要检查它们是否都是非空的 例如: my ($a, $b, $c) = ("", "", ""); # If-clauses for setting the variables here if( !$a || !$b || !$c) { print "Init f

我有一个Perl脚本,在脚本继续之前必须初始化变量。一个冗长的
if
语句,我在其中检查每个变量,这是显而易见的选择。但也许有一种更优雅或简洁的方法来检查几个变量

编辑: 我不需要检查“defined”,它们总是用空字符串定义的,我需要检查它们是否都是非空的

例如:

my ($a, $b, $c) = ("", "", "");

# If-clauses for setting the variables here

if( !$a || !$b || !$c) {
  print "Init failed\n";
}
“初始化”是什么意思?是否具有非“未定义”的值

对于少量值,简单的if检查是最可读/可维护的

if (!$var1 || !$var2 || !$var3) {
    print "ERROR: Some are not defined!"; 
}
顺便说一下,正在检查
$var
是一个可能的错误,因为在Perl中“0”为false,因此初始化为“0”的字符串将无法通过此检查。最好使用
$var eq”“

或者更好的做法是,将内容分隔为>3个值

if    (!$var1          # Use this if your values are guarantee not to be "0"
    || $var2 eq ""     # This is a LOT better since !$var fails on "0" value
    || $var3 eq "") {

    print "ERROR: Some are not defined!"; 
}
如果要检查的值太多,以致上面的内容变得难以读取(尽管如第二个示例中的逐行检查,这种情况从未发生过),或者如果这些值存储在数组中,则可以使用grep来抽象检查:

# We use "length" check instead of "$_ eq ''" as per tchrist's comment below
if (grep { length } ($var1, $var2, $var3, $var4, $var5, @more_args) ) {
    print "ERROR: Some are not defined!"; 
}
如果您必须知道哪些值未定义,则可以使用for循环(留给读者一个明显的练习)或映射技巧:

my $i = -1; # we will be pre-incrementing
if (my @undefined_indexes = map { $i++; $_ ? () : $i }
                                ($var1, $var2, $var3, $var4, $var5, @more_args) ) {

    print "ERROR: Value # $_ not defined!\n" foreach @undefined_indexes; 
}
我假设empty表示空字符串,而不仅仅是任何假值。也就是说,如果
0
“0”
在初始化后始终是有效值,则当前接受的答案将给出错误的结果:

use strict; use warnings;

my ($x, $y, $z) = ('0') x 3;
# my ($x, $y, $z) = ('') x 3;

for my $var ($x, $y, $z) {
    die "Not properly initialized\n" unless defined($var) and length $var;
}
现在,作为验证,这是非常无用的,因为如果出现这种情况,您很可能想知道哪个变量没有正确初始化

最好将配置参数保存在散列中,以便轻松检查哪些参数已正确初始化

use strict; use warnings;

my %params = (
    x => 0,
    y => '',
    z => undef,
);

while ( my ($k, $v) = each %params ) {
    validate_nonempty($v)
        or die "'$k' was not properly initialized\n";
}

sub validate_nonempty {
    my ($v) = @_;
    defined($v) and length $v;
}
或者,如果要列出所有未正确初始化的内容:

my @invalid = grep is_not_initialized($params{$_}), keys %params;
die "Not properly initialized: @invalid\n" if @invalid;

sub is_not_initialized {
    my ($v) = @_;
    not ( defined($v) and length $v );
}

您的方式可读且易于理解,这意味着易于维护。使用以下命令重新启动布尔值:

这样,就不会在每个变量前面加前缀,也不会影响可读性。您可以使用
List::Util
List::MoreUtils
,但它们并不能真正增加可读性

正如SinanÜnür所说,如果将变量放入散列,可以通过散列进行解析,然后列出哪些变量没有初始化。如果有很多这样的变量,并且列表不断变化,这可能是最好的

foreach my $variable qw(a b c d e f g h i j) {
    if (not $param{$variable}) {
        warn qq(You didn't define $variable\n);
    }
}

您可以使用
Getopts::Long
将参数值放入散列中,而不是单独的变量。另外,最新版本的
Getopts::Long
现在可以在任何数组上运行,而不仅仅是
@ARGV

如果您提供一个示例,说明您当前如何操作,包括一个或多个未初始化时的相应反应,您可能会得到更多/更好的答案。(抛出一个错误?将它们设置为默认值?等等)它看起来很奇怪,但它可以工作,并且可以避免我反复键入“| |!”。通过空,OP可能意味着空字符串,而不是false。标准的检查方法是Perl中的
length
。另外,不要使用
$a
$b
,因为它们是
排序
@Sinan使用的包变量:OP声明
$a
$b
my
。这些不是包变量。谢谢你的好意。这种方法似乎不是最具可读性/可维护性的(尽管纯粹从技术角度来看,它确实值得我+1)。“所有”或“任何”来自List::MoreUtils甚至更好。我认为,如果你发现自己显式编写
$\uu
,你可能在Perl中做了一些次优的事情。我特别讨厌
$\u=~/foo/
。我经常为(@list){s/foo/bar/}写
grep{length}@list
map{hex}@list
,或
。甚至
键%h==grep{defined$h{${}}键%h
也可以是
值%h==grep{defined}值%h
。一个闭包表达式足够短,可以在我的脑海中容纳
$\ucode>对于
grep
map
first
all
,&c的“it”的含义。混合访问
$this
$this
的较长代码应该在抽象中加上一个名称:
$\uu
实际上不适用于这一点。@tchrist-这一点很好。根据用户的说明,他正在检查
,而不是
undef
length
是一个不错的选择-编辑。你如何在不使用
$\ucode>的情况下摆脱
undef
@list==grep{defined}@list
来确定它们是否都是,或者
@list=grep{defined}@list
来剔除那些不是的。+1-我知道有一种更有效的方法,但我太懒了,凌晨4点就懒得去寻找:)我对不断地使用模块来处理事情,尤其是非标准的模块,深感矛盾。一方面,我不希望人们对轮子进行彻底的改造,但另一方面,我希望他们能够熟练掌握基本的Perl功能,核心语言本身的运行方式中已经包含了这些功能。+1表示参数的散列,并捕捉到每个人(包括OP)处理“0”时遇到的错误由于中间代码段未初始化,我看不到正在使用sub
validate\u nonempty
。“它需要在那里吗?”马特,谢谢你注意到这一点。是的,它确实需要在那里。。。我一定是在摆弄帖子的时候不小心删除了什么东西。
my @invalid = grep is_not_initialized($params{$_}), keys %params;
die "Not properly initialized: @invalid\n" if @invalid;

sub is_not_initialized {
    my ($v) = @_;
    not ( defined($v) and length $v );
}
if (not($a and $b and $c)) {
   warn(qq(Not all variables are initialized!))
}
foreach my $variable qw(a b c d e f g h i j) {
    if (not $param{$variable}) {
        warn qq(You didn't define $variable\n);
    }
}