如何在 Perl 中检查多个变量是不是为空
Posted
技术标签:
【中文标题】如何在 Perl 中检查多个变量是不是为空【英文标题】:How to check if several variables are empty in Perl如何在 Perl 中检查多个变量是否为空 【发布时间】:2010-11-10 09:19:31 【问题描述】:我有一个 Perl 脚本,其中必须先初始化变量,然后脚本才能继续执行。我检查每个变量的冗长if
语句是显而易见的选择。但也许有一种更优雅或更简洁的方法来检查多个变量。
编辑: 我不需要检查“已定义”,它们总是用一个空字符串定义的,我需要检查它们是否都是非空的。
例子:
my ($a, $b, $c) = ("", "", "");
# If-clauses for setting the variables here
if( !$a || !$b || !$c)
print "Init failed\n";
【问题讨论】:
如果你提供一个你当前如何做的例子,你可能会得到更多/更好的答案,包括如果一个或多个尚未初始化的适当反应。 (抛出错误?将它们设置为默认值?等等) 【参考方案1】:我假设 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 );
【讨论】:
+1 用于参数散列,并捕获包括 OP 在内的每个人都将“0”视为未初始化的错误 在您的中间代码 sn-p 中,我没有看到子validate_nonempty
被使用。它需要在那里吗?
@Matt 感谢您注意到这一点。是的,它确实需要在那里......我一定是在摆弄帖子时不小心删除了一些东西。【参考方案2】:
use List::MoreUtils 'all';
say 'Yes' if (all defined $var1, $var2, $var3);
【讨论】:
+1 - 我知道有一种 MoreUtils 方法可以做到这一点,但凌晨 4 点懒得找 :) 对于不断地转向模块,尤其是非标准模块,我深感矛盾。一方面,我不希望人们严重地重新发明***,但另一方面,我希望他们能够流利地使用基本的 Perl 功能,这些功能已经存在于核心语言本身的运行方式中。【参考方案3】:“初始化”是什么意思?有不是“undef”的值?
对于少量值,直接的 if 检查是恕我直言,最易读/可维护。
if (!$var1 || !$var2 || !$var3)
print "ERROR: Some are not defined!";
顺便说一句,检查!$var
是一个可能的错误,因为“0”在 Perl 中为假,因此初始化为“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;
【讨论】:
我的观点是,如果你发现自己明确写了$_
,你可能在 Perl 中做的事情并不理想。我特别讨厌$_ =~ /foo/
。我经常写grep length @list
、map hex @list
或for (@list) s/foo/bar/
。即使keys %h == grep defined $h$_ keys %h
也可以是values %h == grep defined values %h
。对于grep
,map
,first
,all
,&c,闭包表达式足够短,可以在我的脑海中保存$_
的“它”含义。对$this
和$that
进行混合访问的较长代码值得为抽象命名:$_
并不真正适用。
@tchrist - 好点。鉴于用户澄清他正在检查 ""
而不是 undef
,length
是一个不错的选择 - 已编辑。如果不使用$_
,您将如何摆脱undef
s?
@list == grep defined @list
确定它们是否都是,或者@list = grep defined @list
清除那些不是的。【参考方案4】:
use List::Util 'first';
if (defined first $_ ne "" $a, $b, $c)
warn "empty";
【讨论】:
它看起来很奇怪,但它可以工作并且可以让我免于输入“||!”一遍又一遍。 通过 empty,OP 可能意味着 empty string,而不是 false。检查它的标准方法是 Perl 中的length
。另外,不要使用$a
和$b
,因为它们是sort
使用的包变量。
@Sinan:OP 用my
声明$a
和$b
。这些不是包变量。谢谢你的好点。
这种方法似乎不是最具可读性/可维护性的(尽管它确实值得我为纯粹的技术优点 +1)。
'all' 或 'any' from List::MoreUtils 更好。【参考方案5】:
您的方式可读且易于理解,这意味着它易于维护。使用de Morgan's laws 重述您的布尔值:
if (not($a and $b and $c))
warn(qq(Not all variables are initialized!))
这样,您不会在每个变量前添加 not 前缀,并且不会影响可读性。您可以使用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
。
【讨论】:
以上是关于如何在 Perl 中检查多个变量是不是为空的主要内容,如果未能解决你的问题,请参考以下文章