Program Tip

Perl에서 $ 변수가 정의되어 있고 길이가 0이 아닌 문자열을 포함하는지 어떻게 간결하게 확인할 수 있습니까?

programtip 2020. 10. 19. 12:37
반응형

Perl에서 $ 변수가 정의되어 있고 길이가 0이 아닌 문자열을 포함하는지 어떻게 간결하게 확인할 수 있습니까?


현재 다음 Perl을 사용하여 변수가 정의되어 있고 텍스트가 포함되어 있는지 확인합니다. defined'초기화되지 않은 값'경고를 피하기 위해 먼저 확인 해야합니다.

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

이것을 작성하는 더 나은 (아마 더 간결한) 방법이 있습니까?


정의 확인을 자주 볼 수 있으므로 undef 값 사용에 대한 경고를 처리 할 필요가 없습니다 (Perl 5.10에서는 문제가되는 변수를 알려줍니다).

 Use of uninitialized value $name in ...

그래서이 경고를 피하기 위해 사람들은 온갖 종류의 코드를 생각해 내고 그 코드는 풍선 껌과 덕트 테이프가 아닌 솔루션의 중요한 부분처럼 보이기 시작합니다. 때로는 피하려는 경고를 명시 적으로 해제하여 수행중인 작업을 표시하는 것이 더 좋습니다.

 {
 no warnings 'uninitialized';

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

다른 경우에는 데이터 대신 일종의 null 값을 사용하십시오. 함께 펄 5.10의 정의 또는 운영자는 , 당신이 줄 수있는 length대신 경고를 트리거 할 변수의 명시 적 빈 문자열 (정의를 다시 제로 길이를 줄) :

 use 5.010;

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

Perl 5.12에서는 length정의되지 않은 값에서도 undefined를 반환 하기 때문에 조금 더 쉽습니다 . 그것은 약간 어리석은 것처럼 보일지 모르지만 그것은 내가되고 싶었던 수학자를 기쁘게합니다. 그것은 경고를 발행하지 않으며, 이것이이 질문이 존재하는 이유입니다.

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정의되지 않은 경우 논리 흐름이 의도 한대로 작동하지만 사용중인 경우 warnings(그리고 그래야만하는 경우) 다음과 같은 경고를 받게됩니다.

문자열 ne에서 초기화되지 않은 값 사용

따라서 $name정의되지 않을 가능성이 있는 경우 해당 경고를 피하기 위해 무엇보다도 먼저 정의를 확인해야합니다. Sinan Ünür가 지적했듯이 Scalar :: MoreUtils사용하면 다음과 같은 empty()방법을 통해 바로 그 작업을 수행하는 코드 (정의성을 확인한 다음 길이가 0인지 확인)를 얻을 수 있습니다 .

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

첫째, length항상 음수가 아닌 숫자를 반환하므로

if ( length $name )

if ( length $name > 0 )

동등합니다.

정의되지 않은 값을 빈 문자열로 대체해도 괜찮다 //=면 LHS가 정의되지 않은 한 RHS를 LHS에 할당하는 Perl 5.10 연산자를 사용할 수 있습니다 .

#!/usr/bin/perl

use feature qw( say );
use strict; use warnings;

my $name;

say 'nonempty' if length($name //= '');
say "'$name'";

$name정의되지 않은 경우 빈 문자열이 할당되므로 초기화되지 않은 변수에 대한 경고 가 없습니다.

그러나 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";

당신은 소지품하지 않을 경우 $name, 사용 default.


변수가 undef같거나 같은지 상관하지 않는 경우 ''일반적으로 다음과 같이 요약합니다.

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

넌 말할 수있다

 $name ne ""

대신에

 length $name > 0

단순하고 우아한 방식으로 반복적 인 작업을 수행하는 것이 항상 가능한 것은 아닙니다.

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.

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

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).


The excellent library Type::Tiny provides 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.

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

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

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

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

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 $name is the numeric value 0 or the string '0', but will behave the same in all other cases.

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

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

This will decide what to get the length of based on whether $name is 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.


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
}

참고URL : https://stackoverflow.com/questions/1480066/in-perl-how-can-i-concisely-check-if-a-variable-is-defined-and-contains-a-non

반응형