Raphael Rafatpanah
Raphael Rafatpanah

Reputation: 19967

How to check if a variable (e.g. $3) exists so that I don't get a warning about "uninitialized value"?

I am trying to run a script on a .csv file that converts sizes in feet and inches to separate columns of width in inches and height in inches.

It works fine when not using strict mode, but returns a warning message when use warnings; is set.

My problem occurs here:

if ($data[$index_num] =~ /(\d+)'( (\d+)'')? x (\d+)'( (\d+)'')?/) {

    my $width = $1*12+$3;
    my $height = $4*12+$6;

    ...
}

Since sometimes the size could be 5' x 8' the special variables $3 and $6 do not exist.

All possible size formats are as follows:

  1. 5' 1'' x 6' 7'' (All Single Digits)
  2. 10' 1'' x 5' 10'' (Combination of Single and Double Digits)
  3. 5' x 8' (No Inches)
  4. 4' 6'' x 7' (Combination of No Inches and Inches)

The warning I receive is:

Use of uninitialized value $6 in addition (+) at script.pl line 47, line 567.

This is happening in either case 3 or 4 where the inches are missing on either the width or height.

How can I check to see if either $3 or $6 exists before trying to use them?

Upvotes: 1

Views: 398

Answers (3)

ikegami
ikegami

Reputation: 385657

First, let's get rid of useless captures:

/(\d+)'(?: (\d+)'')? x (\d+)'(?: (\d+)'')?/

Captures that didn't match are set to undef, so you can used defined or //.

my $width  = $1 * 12 + ($2 // 0);
my $height = $3 * 12 + ($4 // 0);

// was introduced in Perl 5.10. For backwards compatibility, you can use the following:

my $width  = $1 * 12 + ($2 || 0);
my $height = $3 * 12 + ($4 || 0);

The second version uses zero when $2 (or $4) is false (undef, zero, or empty string) rather than undef, but that's perfectly fine here.

Upvotes: 10

PP.
PP.

Reputation: 10864

If you just want to test for a number AND you're happy to calculate a result when there is no match then you could say:


if ($data[$index_num] =~ /(\d+)\'( (\d+)\'\')? x (\d+)\'( (\d+)\'\')?/) {

    my $width = ( $1 || 0 ) * 12 + ( $3 || 0 );
    my $height = ( $4 || 0 ) * 12 + ( $6 || 0 );

    ...
}

Why does this work? Because if, say, $1 is undefined, then ($1 || 0) returns the right-hand side, or 0. Likewise if $1 is zero then the left-hand-side of the OR condition will also fail but return 0 nonetheless. And if $1 is non-zero and defined then the left-hand-side will be returned ($1).

If you're going to use the || technique then ensure you put the left-hand and right-hand sides inside parenthesis to avoid operator-precedence side effects.

Upvotes: 3

user4035
user4035

Reputation: 23729

You can use defined function:

my $height;
if(defined($6))
{
    $height = $4*12+$6;
}
else
{
    $height = $4*12;
}

Upvotes: 12

Related Questions