string 在 Perl 中,如何简洁地检查 $variable 是否已定义并包含非零长度字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1480066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 00:32:50  来源:igfitidea点击:

In Perl, how can I concisely check if a $variable is defined and contains a non zero length string?

perlstring

提问by Jessica

I currently use the following Perl to check if a variable is defined and contains text. I have to check definedfirst to avoid an 'uninitialized value' warning:

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

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

Is there a better (presumably more concise) way to write this?

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

采纳答案by brian d foy

You often see the check for definedness so you don't have to deal with the warning for using an undef value (and in Perl 5.10 it tells you the offending variable):

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

 Use of uninitialized value $name in ...

So, to get around this warning, people come up with all sorts of code, and that code starts to look like an important part of the solution rather than the bubble gum and duct tape that it is. Sometimes, it's better to show what you are doing by explicitly turning off the warning that you are trying to avoid:

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

 {
 no warnings 'uninitialized';

 if( length $name ) {
      ...
      }
 }

In other cases, use some sort of null value instead of the data. With Perl 5.10's defined-or operator, you can give lengthan explicit empty string (defined, and give back zero length) instead of the variable that will trigger the warning:

在其他情况下,使用某种空值而不是数据。使用Perl 5.10 的 defined-or operator,您可以给出length一个明确的空字符串(定义,并返回零长度)而不是将触发警告的变量:

 use 5.010;

 if( length( $name // '' ) ) {
      ...
      }

In Perl 5.12, it's a bit easier because lengthon an undefined value also returns undefined. That might seem like a bit of silliness, but that pleases the mathematician I might have wanted to be. That doesn't issue a warning, which is the reason this question exists.

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

use 5.012;
use warnings;

my $name;

if( length $name ) { # no warning
    ...
    }

回答by Adam Bellaire

As mobrule indicates, you could use the following instead for a small savings:

正如 mobrule 所指出的,您可以使用以下内容来节省一点:

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

You could ditch the defined check and get something even shorter, e.g.:

您可以放弃定义的检查并获得更短的内容,例如:

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

But in the case where $nameis not defined, although the logic flow will work just as intended, if you are using warnings(and you should be), then you'll get the following admonishment:

但是在$name没有定义where 的情况下,虽然逻辑流程会按预期工作,但如果您正在使用warnings(并且您应该这样做),那么您将得到以下警告:

Use of uninitialized value in string ne

So, if there's a chance that $namemight not be defined, you really do need to check for definedness first and foremost in order to avoid that warning. As Sinan ünür points out, you can use Scalar::MoreUtilsto get code that does exactly that (checks for definedness, then checks for zero length) out of the box, via the empty()method:

因此,如果有$name可能未定义的机会,您确实需要首先检查定义性,以避免出现该警告。正如 Sinan ünür 指出的那样,您可以使用Scalar::MoreUtils通过以下方法获得开箱即用的代码(检查定义性,然后检查零长度)empty()

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

回答by Sinan ünür

First, since lengthalways returns a non-negative number,

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

if ( length $name )

and

if ( length $name > 0 )

are equivalent.

是等价的。

If you are OK with replacing an undefined value with an empty string, you can use Perl 5.10's //=operator which assigns the RHS to the LHS unless the LHS is defined:

如果您可以用空字符串替换未定义的值,则可以使用 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'";

Note the absence of warnings about an uninitialized variable as $nameis assigned the empty string if it is undefined.

请注意没有关于未初始化变量的警告,因为$name如果未定义,则分配空字符串。

However, if you do not want to depend on 5.10 being installed, use the functions provided by Scalar::MoreUtils. For example, the above can be written as:

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

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

If you don't want to clobber $name, use default.

如果您不想破坏$name,请使用default.

回答by Gaurav

In cases where I don't care whether the variable is undefor equal to '', I usually summarize it as:

在我不关心变量是否undef等于 的情况下'',我通常将其总结为:

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

回答by daotoad

The excellent library Type::Tinyprovides an framework with which to build type-checking into your Perl code. What I show here is only the thinnest tip of the iceberg and is using Type::Tiny in the most simplistic and manual way.

优秀的库Type::Tiny提供了一个框架,用于在 Perl 代码中构建类型检查。我在这里展示的只是冰山一角,并且以最简单和手动的方式使用 Type::Tiny。

Be sure to check out the Type::Tiny::Manualfor more information.

请务必查看Type::Tiny::Manual以获取更多信息。

use Types::Common::String qw< NonEmptyStr >;

if ( NonEmptyStr->check($name) ) {
    # Do something here.
}

NonEmptyStr->($name);  # Throw an exception if validation fails

回答by daotoad

It isn't always possible to do repetitive things in a simple and elegant way.

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

Just do what you always do when you have common code that gets replicated across many projects:

当您拥有可在多个项目中复制的通用代码时,只需执行您经常执行的操作:

Search CPAN, someone may have already the code for you. For this issue I found Scalar::MoreUtils.

搜索 CPAN,有人可能已经为您准备了代码。对于这个问题,我找到了Scalar::MoreUtils

If you don't find something you like on CPAN, make a module and put the code in a subroutine:

如果你在 CPAN 上没有找到你喜欢的东西,那就制作一个模块并将代码放在一个子程序中:

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

Then in your code call it:

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

use My::String::Util qw( is_nonempty );

if ( is_nonempty $name ) {
    # do something with $name
}

Or if you object to prototypes and don't object to the extra parens, skip the prototype in the module, and call it like: is_nonempty($name).

或者,如果你反对原型和不反对多余的括号,跳过模块中的原型,并调用它像:is_nonempty($name)

回答by mob

You could say

你可以说

 $name ne ""

instead of

代替

 length $name > 0

回答by Dave Sherohman

How about

怎么样

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

This isn't quite equivalent to your original version, as it will also return false if $nameis the numeric value 0 or the string '0', but will behave the same in all other cases.

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

In perl 5.10 (or later), the appropriate approach would be to use the defined-or operator instead:

在 perl 5.10(或更高版本)中,适当的方法是使用 defined-or 运算符:

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

This will decide what to get the length of based on whether $nameis defined, rather than whether it's true, so 0/'0'will handle those cases correctly, but it requires a more recent version of perl than many people have available.

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

回答by Joseph

if ($name )
{
    #since undef and '' both evaluate to false 
    #this should work only when string is defined and non-empty...
    #unless you're expecting someting like $name="0" which is false.
    #notice though that $name="00" is not false
}