在Perl中,如何简洁地检查$ variable是否被定义并且包含一个非零长度的string?

我目前使用下面的Perl来检查variables是否被定义并包含文本。 我必须首先检查defined以避免“未初始化的值”警告:

 if (defined $name && length $name > 0) { # do something with $name } 

有没有更好的(可能更简洁)的方式来写这个?

您经常会看到定义的检查,因此您不必处理使用undef值的警告(在Perl 5.10中它会告诉您有问题的variables):

  Use of uninitialized value $name in ... 

所以,为了解决这个警告,人们提出了各种各样的代码,代码开始看起来像解决scheme的重要部分,而不是泡泡糖和胶带。 有时候,最好通过明确地关掉你试图避免的警告来显示你在做什么:

  { no warnings 'uninitialized'; if( length $name ) { ... } } 

在其他情况下,使用某种空值而不是数据。 使用Perl 5.10的定义或运算符 ,您可以给length一个明确的空string(定义,并返回零长度),而不是会触发警告的variables:

  use 5.010; if( length( $name // '' ) ) { ... } 

在Perl 5.12中,它更容易一些,因为未定义的值的length也会返回undefined 。 这可能看起来有些愚蠢,但是那让我想成为的math家感到高兴。 这不会发出警告,这是这个问题存在的原因。

 use 5.012; use warnings; my $name; if( length $name ) { # no warning ... } 

正如mobrule所指出的那样,你可以使用下面的代码来节省一些资源:

 if (defined $name && $name ne '') { # do something with $name } 

你可以放弃定义的检查,并得到更短的东西,例如:

 if ($name ne '') { # do something with $name } 

但是在$name没有被定义的情况下,虽然逻辑stream程可以像预期的那样工作,但是如果你正在使用warnings (你应该是),那么你会得到以下的警告:

 在stringne中使用未初始化的值 

所以,如果有可能没有定义$name ,那么确实需要首先检查定义,以避免该警告。 正如SinanÜnür指出的那样,您可以使用Scalar :: MoreUtils通过empty()方法获得代码,这些代码完全符合(检查定义,然后检查长度为零)开箱即用:

 use Scalar::MoreUtils qw(empty); if(not empty($name)) { # do something with $name } 

首先,由于length总是返回一个非负数,

 if ( length $name ) 

 if ( length $name > 0 ) 

是等同的。

如果你可以用一个空stringreplace一个未定义的值,你可以使用Perl 5.10的//=运算符,它将RHS赋给LHS,除非定​​义了LHS:

 #!/usr/bin/perl use feature qw( say ); use strict; use warnings; my $name; say 'nonempty' if length($name //= ''); say "'$name'"; 

请注意,没有关于未初始化的variables的警告,因为如果未定义,则$name被分配空string。

但是,如果您不想依赖5.10被安装,请使用Scalar :: MoreUtils提供的function。 例如,上面可以写成:

 #!/usr/bin/perl use strict; use warnings; use Scalar::MoreUtils qw( define ); my $name; print "nonempty\n" if length($name = define $name); print "'$name'\n"; 

如果你不想贬值$name ,使用default

如果我不关心这个variables是不是undef或者等于'' ,我通常总结为:

 $name = "" unless defined $name; if($name ne '') { # do something with $name } 

你可以说

  $name ne "" 

代替

  length $name > 0 

以简单和优雅的方式做重复的事情并不总是可能的。

只要做一些常用的代码就可以在许多项目中复制:

searchCPAN,有人可能已经为你的代码。 对于这个问题,我find了Scalar :: MoreUtils 。

如果你没有在CPAN上罚款你想要的东西,build立一个模块并把代码放在一个子程序中:

 package My::String::Util; use strict; use warnings; our @ISA = qw( Exporter ); our @EXPORT = (); our @EXPORT_OK = qw( is_nonempty); use Carp qw(croak); sub is_nonempty ($) { croak "is_nonempty() requires an argument" unless @_ == 1; no warnings 'uninitialized'; return( defined $_[0] and length $_[0] != 0 ); } 1; =head1 BOILERPLATE POD blah blah blah =head3 is_nonempty Returns true if the argument is defined and has non-zero length. More boilerplate POD. =cut 

然后在你的代码中调用它:

 use My::String::Util qw( is_nonempty ); if ( is_nonempty $name ) { # do something with $name } 

或者,如果您反对原型而不反对额外的参数,则跳过模块中的原型,并将其称为: is_nonempty($name)

 my %hash ; $hash{"what"} = "What"; $hash{"how"} = "How"; my $word = $hash{"now"}; print $word; if (! $word) { print "Catch Ya\n"; } else { print $word ; } 

怎么样

 if (length ($name || '')) { # do something with $name } 

这与您的原始版本并不完全相同,因为如果$name是数字值0或string'0' ,它也会返回false,但在所有其他情况下的行为将相同。

在perl 5.10(或更高版本)中,适当的方法是使用定义的或运算符来代替:

 use feature ':5.10'; if (length ($name // '')) { # do something with $name } 

这将决定根据是否定义$name来确定要获取的长度,而不是确定是否为真,所以0 / '0'将正确处理这些情况,但它需要比许多人可用的更新版本的perl。

如果($ name)
 {
     #自从undef和“都评价为false 
     #这应该只有当string定义和非空...
     #unless你期待有点像$ name =“0”这是假的。
     #notice虽然该名称=“00”是不是假的
 }