[perl] 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
답변
단순하고 우아한 방식으로 반복적 인 작업을 수행하는 것이 항상 가능한 것은 아닙니다.
여러 프로젝트에서 복제되는 공통 코드가있을 때 항상 수행하는 작업을 수행하십시오.
CPAN을 검색하면 누군가 이미 코드를 가지고있을 수 있습니다. 이 문제에 대해 Scalar :: MoreUtils를 찾았 습니다 .
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
그런 다음 코드에서 다음을 호출하십시오.
use My::String::Util qw( is_nonempty );
if ( is_nonempty $name ) {
# do something with $name
}
또는 프로토 타입에 반대하고 추가 괄호에 반대하지 않는 경우 모듈에서 프로토 타입을 건너 뛰고 다음과 같이 호출합니다 is_nonempty($name)
..
답변
우수한 라이브러리 Type :: Tiny 는 Perl 코드에 유형 검사를 빌드 할 수있는 프레임 워크를 제공합니다. 제가 여기서 보여 드리는 것은 빙산의 가장 얇은 일각 일 뿐이며 Type :: Tiny를 가장 단순하고 수동적 인 방식으로 사용하고 있습니다.
자세한 내용 은 Type :: Tiny :: Manual 을 확인하세요.
use Types::Common::String qw< NonEmptyStr >;
if ( NonEmptyStr->check($name) ) {
# Do something here.
}
NonEmptyStr->($name); # Throw an exception if validation fails