In Perl, how can I clearly check if the variable $ is defined and contains a string with zero length?

I am currently using the following Perl to check if a variable is defined and contains text. First I have to check defined to avoid the warning "uninitialized value":

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

Is there a better (supposedly shorter) way to write this?

+68
string perl
Sep 26 '09 at 0:23
source share
9 answers

You often see a certainty check, so you don’t have to deal with a warning about using the undef value (and in Perl 5.10 it tells you an abusive variable):

  Use of uninitialized value $name in ... 

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

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

In other cases, instead of data, you need to use some zero value. Using a Perl 5.10 specific or operator , you can give length explicit empty string (defined and return zero length) instead of a variable, this will raise a warning:

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

In Perl 5.12, this is a bit simpler because length in the value undefined also returns undefined . It may seem a little stupid, but it pleases the math I might have wanted to be. This does not raise a warning, so there is a reason for this.

 use 5.012; use warnings; my $name; if( length $name ) { # no warning ... } 
+66
Sep 26 '09 at 19:27
source share

As the mobrule function shows, you can use the following to save a little:

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

You can do a specific check and get something even shorter, for example:

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

But in the case where $name not defined, although the logical thread will work as intended, if you use warnings (and you should be), you will receive the following warning:

  Use of uninitialized value in string ne 

So, if there is a chance that $name cannot be determined, you really need to check for certainty first and foremost to avoid this warning. As Sinan Ünür points out, you can use Scalar :: MoreUtils to get code that does just that (checks for certainty, then checks for zero length) from the box, using the empty() method:

 use Scalar::MoreUtils qw(empty); if(not empty($name)) { # do something with $name } 
+19
Sep 26 '09 at 0:44
source share

First, since length always returns a non-negative number,

 if ( length $name ) 

and

 if ( length $name > 0 ) 

are equivalent.

If you agree to replace the undefined value with an empty string, you can use the Perl 5.10 //= operator, which assigns RHS to LHS if LHS is not defined:

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

Note that there are no warnings about an uninitialized variable, because $name assigned an empty string if it is undefined.

However, if you do not want to depend on the installation of 5.10, use the Scalar :: MoreUtils functions . For example, the above may be written as:

 #!/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 do not want clobber $name , use default .

+13
Sep 26 '09 at 10:07
source share

In cases where it doesn’t matter to me whether the variable is undef or equal to, '' I usually summarize it as:

 $name = "" unless defined $name; if($name ne '') { # do something with $name } 
+6
Sep 28 '09 at 6:29
source share

Can say

  $name ne "" 

instead

  length $name > 0 
+2
Sep 26 '09 at 0:29
source share

It is not always possible to do repetitive things in a simple and elegant way.

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

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

If you haven't fined something that 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 name it:

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

Or, if you mind prototypes and don't mind additional parsers, skip the prototype in the module and name it like this: is_nonempty($name) .

+2
Sep 26 '09 at 1:33
source share
 my %hash ; $hash{"what"} = "What"; $hash{"how"} = "How"; my $word = $hash{"now"}; print $word; if (! $word) { print "Catch Ya\n"; } else { print $word ; } 
0
Jan 28 '14 at 22:02
source share

What about

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

This is not exactly equivalent to the original version, as it will also return false if $name is a numeric value of 0 or the string '0' , but will behave the same in all other cases.

In perl 5.10 (or later), a suitable approach would be to use a specific or operator instead:

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

This will decide to get the length based on the definition of $name , not true, so 0 / '0' will handle these cases correctly, but it requires a newer version of perl than many people have available.

-one
Sep 26 '09 at 10:04
source share
 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
 }
-3
Sep 29 '09 at 13:23
source share



All Articles