Perl if statement

The if statement will execute a block only when a conditional expression is evaluated as true; whether the expression is true, the block between the curly braces will be executed.

The if statement let you execute a block of statements between two curly braces if a boolean condition is evaluated true, otherwise the execution continues with the following block, either an elsif/else block or after the end of the if statement.

You may scope some of your variables with my keyword in the control condition and in this case the scope of the variables extends from its declaration through the rest of the Perl if statement, including any elsif or else clause.

There is an alternative to the Perl if statement: the unless statement. Regardless the if statement which executes a block of code if a condition is true, the unless statement executes a block of code if the condition is false. You can regard the unless statement like the negative or opposite of if. Sometimes it is useful to use unless instead of if, especially when you want to optimize your code or to make it more legible.

You have two syntax forms for the if conditional statement: a general form and a short form where if is used as a modifier.

The general syntax form is as follows:

if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
where:
  • EXPR is a Boolean conditional expression
  • the elsif and else clauses are optional and are used if you want to check a certain sequence of conditional expressions and find out which one of them is true
  • BLOCK consists of one or more statements enclosed in curly braces; in the construction of a block, the curly braces are always required.

You can split the general conditional if statement as follows:

a simple if statement

if (EXPR) BLOCK
If the EXPR condition will be evaluated true, Perl interpreter will execute the BLOCK, otherwise it will skip to the statement or declaration after the block. In this format you use neither the else nor the elsif clauses.

if-else format

if (EXPR) BLOCK else BLOCK
Perl will evaluate the conditional EXPR and if the result is true, it will continue with the execution of the BLOCK after the conditional expression, otherwise the script will continue with the block that follows the else clause.

if-elsif-else format

if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
This is the general format. If you have more than one branch in a conditional statement, you can use the Perl if statement in connection with elsif clause that allows you to check as many conditional expressions as you need. You can finish the compound conditional statement using the else clause at the end of the form.

The syntax form where if is used as an expression modifier

You can use if as a modifier, too. An expression modifier means a normal expression followed by a modifier that controls the execution of that expression.

The appropriate syntax form is as follows:

EXPR_MODIFIER if (EXPR)
Perl will execute the above construction from right to left: the EXPR condition will be evaluated first and if the condition is true, Perl will continue the execution of the code with the EXPR_MODIFIER that precedes the Perl if statement.

If the EXPR condition is false, the Perl interpreter will skip to the following line of code. You can use this form when your conditional statement has no more than one branch.

One of the simplest syntax form of the if statement is as follows:

if (EXPR) BLOCK
Perl will evaluate the EXPR and if it is true, it will execute the code between the curly braces of the block.

Otherwise, the script will continue with the next statement after the block. Neither elsif nor else clauses are used in the above format.

See the following code snippet:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $a = -1;
 
if($a < 0) {
  $a += 2; 
}
 
print "a = $a\n";  # it outputs a = 1
The Perl interpreter will check the condition between parentheses and if the result is true, it will increment the $a scalar variable value with 2. It is possible that EXPR doesn’t mean a condition, like in the following example: 
if(1) {
  $a = 1;
}
Because the expression is true, the Perl interpreter will continue with the execution of the block, i.e. it will assign the value 1 to the $a scalar variable. As you guess, in this example you don’t need to use the Perl if statement at all, the assign statement $a = 1 is sufficient to do the job.

The syntax form of the if statement with the else clause is as follows:

if (EXPR) BLOCK else BLOCK
Perl will evaluate the conditional EXPR and if the result is true, the execution of the script will continue with the block that follows the conditional expression; otherwise, the script execution will skip inside the block that is after the else clause.
 
Let’s look at a simple example where we need to find the maximum of two numbers:
#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($a, $b) = (15, 27);
 
if($a > $b) {
  print "max($a, $b) = $a\n";
} else {
  print "max($a, $b) = $b\n";
}
 
# it prints: max(15, 27) = 27
Well, there is a shorter way to do this by using the logical ternary operator? also called the conditional operator. I remind you briefly that the ternary operator (named ternary because it uses three operands) is like an if-else compound statement both included into an expression.

Please note that this operator is an expression that returns a value based on the conditional statement it evaluates. It can be used by following the syntax:

EXPR ? true-value : false-value

With the ternary operator, you can rewrite the above code like so:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($a, $b) = (15, 27);
 
print "max($a, $b) = ", $a > $b ? $a : $b,"\n";
 
# it prints: max(15, 27) = 27

The syntax form of the Perl if statement with the else clause is as follows:

if (EXPR) BLOCK else BLOCK
A particular case it is when the if statement has an empty block after the expression, like in the following snippet code example:
#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($a, $b) = (12, -25);
 
if($a*$b >= 0 && $a + $b >= 0) {
  # do nothing
}
else {
  print "at least $a or $b is negative\n";
}
There are at least two ways to get rid of the empty if block. One way is to use the unless statement instead of the if statement: 
#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($a, $b) = (12, -25);
 
unless($a*$b >= 0 && $a + $b  >= 0) {
  print "at least $a or $b is negative\n";
}
In writing the conditional statements, you can swap as you wish between the if and the unless in order to make your code more readable.

Another way is to rewrite the conditional expression enclosed between the parentheses that follow the if keyword: ($a*$b >= 0 && $a+$b >= 0).

This is a boolean expression and as you expect Perl provides you with the logical AND operator (&&) and the logical OR operator (||) in order to manipulate the boolean expressions. When you use the && and || operators be careful not to include any spaces between the symbols ("& &" or "| |" is wrong) because you’ll get something you couldn’t expect.

So you can rewrite the above condition in order to get rid of the empty block:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($a, $b) = (12, -25);
 
if($a*$b < 0) {
  print "at least $a or $b is negative\n";
}

The syntax form associated with the elsif clause allows you to check as many conditional expressions as are required. The else clause from the end of the syntax form is still optional but you can use it at the end of the Perl if statement if all other tests fail – with other words, the block of the final else will be executed if none of the conditions are true.

See the general syntax form:

if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
See an example about how to implement it:
#!/usr/local/bin/perl
 
use strict;
use warnings;
 
chomp (my $line = <STDIN>);
$line = lc $line;
 
if($line eq "index"){
  print "index function\n";
} elsif ($line eq "chomp") {
  print "chomp function\n";
} elsif ($line eq "hex") {
  print "hex function\n";
} elsif ($line eq "substr") {
  print "substr function\n";
} else {
  print "$line: unknown function\n";
}
In this example we read a line from <STDIN>, remove the last newline with the chomp function and convert all the characters in lowercase. Next we check if the text read from <STDIN> is one of the following functions: index, chomp, hex or substr. If we don’t find any occurrence, the script program will execute the block that follows the else clause.

Please note that the Perl interpreter must evaluate all the elsif alternatives you provide in an if statement. If there are too many, you need to reconsider a more efficient way to write the code, like emulate a case or switch statement (in Perl 5.10 you can use the given function).

An expression modifier means a normal expression followed by a modifier that controls the execution of that expression.

The appropriate syntax form is as follows:

EXPR_MODIFIER if (EXPR)
Perl will execute the above construction from right to left: the EXPR condition will be evaluated first and if the condition is true, Perl will continue the execution of the code with the EXPR_MODIFIER that precedes the Perl if statement.

If the EXPR condition is false, the Perl interpreter will skip to the following line of code. You can use this form when your conditional statement has one branch only.

See the next example about how to use it:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $debug = 1;
my ($a, $b) = (1, 2);
#  some statements here
print "a = $a\n" if $debug;   # check the $a value
#  other statements
print "b = $b\n" if $debug;   # check the $b value
# the rest of script statements
If you want to print the debug messages, at the beginning of the script you need to set the $debug variable value to 1, otherwise to 0.

The exists function is useful to check if a key exists in a hash. See the following example where we use the Perl if statement to check if a hash key exists:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
# initialize a hash
my %hash;
$hash{1} = 'one';
$hash{3} = 'three';
$hash{5} = 'five';
$hash{7} = 'seven';
 
foreach my $key (1..8) {
  print "Key found: $key\n" if exists $hash{$key};
}
The above hash has as keys the numbers 1, 3, 5 and 7. The foreach loop is used to iterate over the (1..8) set. The print function will display the hash keys that are found in this set.

This code produces the following output:

Key found: 1
Key found: 3
Key found: 5
Key found: 7
 

See the following snippet code:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
while (my $line = <STDIN>) {
  chomp $line;
  last if lc ($line) =~ /quit/;
  next if length $line == 0;
  print "Line: $line\n";
}
Here, we’re reading a line at a time into $line; inside the while loop, at each iteration step:
 
  • the chomp function will remove the trailing newline from $line
  • the last control will finish the loop if the $line contains the word quit (the lc function is used to make the conditional test case insensitive)
  • the next control will reiterate the loop if the line read from STDIN is empty
  • in the case the $line is not empty, the content of $line will be printed

You can use the Perl if statement to check if a variable is defined or not. Anytime you declare a variable in Perl without initializing it, automatically it will take the "undef" value (which is different either of 0 or ""). So you use the defined function to check-up if a variable is defined (it was assigned some value to it) or has the "undef" value.

Applied to aggregate types (such as arrays and hashes), defined is depreciated and does not tell you anything useful about that aggregate, but you can apply it to the aggregate elements. 

The following code snippet shows you how to use Perl if and defined for scalar variables:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($a, $b) = (1);
print "\$a is defined\n" if defined($a);
print "\$b is not defined\n" if !defined($b);
The following example is for the elements of an array:
#!/usr/local/bin/perl
 
use strict;
use warnings;
 
# initializing an array
my @array = qw(zero one two three four);
 
$array[7] = "seven";
$array[9] = "nine";
 
for(my $i=0; $i<=20; $i++) {
  print $array[$i]," " if defined($array[$i]);
}
print "\n";
# it displays: zero one two three four seven nine
 

In Perl the most part of the functions is returning something, so you can use them with the conditional if statement in order to check the returned value.

For example, you can use the exists function to check if a particular key exists in a hash. The exists function returns true if the specified element in the hash has ever been initialized, even if the corresponding value is undefined.

See the following code snippet:

#!/usr/local/bin/perl
 
use warnings;
use strict;
 
# define a hash
 
my %colors = (blue => 2, green => 5, yellow => 7, white => undef);
 
# check for the key existence
 
print ("Found key: white\n") if (exists($colors{white}));
# it prints: Found key: white
Or you can use the index function to check if a string is a substring of another. The index function returns -1 if the substring is not found.

You can use the index function in a conditional test, by testing if the returning value is greater or equal to 0 for success:

#!/usr/local/bin/perl
 
use warnings;
use strict;
 
my $someText = "Learning Perl Language";
 
if((my $pos = index($someText, "Perl")) >= 0) {
  print "The text was located at the position $pos\n";
}
 
# it prints: The text was located at the position 9
Or you can replace the line of code that contains the if statement with:
 
if((my $pos = index($someText, "Perl")) > -1) {
and the result produced by running the code will be the same.

If you want to find out if a substring matches a bigger string and you don’t care about the substring position within the string, you can use a single line of code, like in the following example:

print "Found it!\n" if(index($someText, "Perl")>-1);

An easy way to find if a variable is a simple string or number, or a reference to an array or a hash or something else, is to use the ref function. The ref function has the following syntax form:

ref EXPR
Whether EXPR is not specified, $_ will be used. This function returns an empty string whether EXPR/$_ is not a reference, and a string (the type of reference) otherwise. Look at the code below to see how it works using a foreach loop and a compound Perl if-elsif-else statement:
 
#!/usr/local/bin/perl
 
use warnings;
use strict;
 
# define some simple variables
# we can use the same name  colors for different things
my $colors = "darkblue";
my @colors = qw(blue red yellow brown);
my %colors = (c1 => "blue", c2 => "green", c3 => "yellow");
 
# define a hash with references
my %moreColors = (1 => "white", 2 => \$colors,
 3 => \@colors, 4 => \%colors);
 
# loop through %moreColors hash to find out the references
foreach my $key (keys %moreColors)
{
  if (ref $moreColors{$key} eq "SCALAR") {
    print "$key: SCALAR\n";
  } elsif (ref $moreColors{$key} eq "ARRAY") {
    print "$key: ARRAY\n";
  } elsif (ref $moreColors{$key} eq "HASH") {
    print "$key: HASH\n";
  } elsif (ref $moreColors{$key} eq "") {
    print "$key: NO REFERENCE\n";
  } else {
    print "$key: UNKNOWN\n";
  }
}
And here is what you get as output if you run the code:
 
4: HASH
1: NO REFERENCE
3: ARRAY
2: SCALAR
 
Do you see the order (4 1 3 2) in which the keys were printed? Perl doesn’t care about the sequential order (1 2 3 4) in which I initialized %moreColors hash! Remember, if you want to print hashes in some order, you must sort the hashes yourself.

As a conditional statement, the Perl if statement may need to use the logical operators to test and compare one value to another.

The logical operator && is a binary operator and it is used to determine if both operands are true.

This operator is a C-style operator but in Perl it has some additional meaning.

For example, the expression (E1 && E2) will be evaluated from left to right.

If E1 is evaluated false, the expression E2 will be no more evaluated, because the result will be false, either E2 is true or false.

That’s why in Perl this operator is known as a short-circuit operator, too (because it is evaluated the fewest number of operands possible).

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($u, $v) = (1, 1);
 
if ($u++ > 0 && $v++ > 0) {
  print "True, \$u = $u, \$v = $v\n"
}
else {
  print "False, \$u = $u, \$v = $v\n"
}
# it expects: True, $u = 2, $v = 2
 
($u, $v) = (1, 1);
if ($u++ < 0 && $v++ > 0) {
  print "True, \$u = $u, \$v = $v\n"
}
else {
  print "False, \$u = $u, \$v = $v\n"
}
# it expects: False, $u = 2, $v = 1
In the above example, the increment ++ operators has the meaning to show you if an expression (like $v++ > 0) was evaluated or not.

You can use a short-circuit operator without the involving of a conditional statement. See the next short example:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $u = 1;
$u == 1 && print "\$u = 1\n";
# it prints: $u = 1
Here, the condition $u == 1 is true so Perl will continue with the evaluating of the second operand and the print statement will be executed.

Another short-circuit operator is OR (||).

As a conditional statement, the Perl if statement may need to use the logical operators to test and compare one value to another. The logical operator || is a binary operator and it is used to determine if either of operands is true. This operator is a C-style operator but in Perl it has some additional meaning.

For example, the expression (E1 || E2) will be evaluated from left to right. If E1 is evaluated true, the expression E2 will be no more evaluated, because the result will be true, either E2 is true or false. That’s why in Perl this operator is known as a short-circuit operator, too (because it is evaluated the fewest number of operands possible).

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($u, $v) = (1, 1);
 
if ($u++ > 0 || $v++ > 0) {
  print "True, \$u = $u, \$v = $v\n"
}
else {
  print "False, \$u = $u, \$v = $v\n"
}
# it expects: True, $u = 2, $v = 1
 
($u, $v) = (1, 1);
if ($u++ < 0 || $v++ > 0) {
  print "True, \$u = $u, \$v = $v\n"
}
else {
  print "False, \$u = $u, \$v = $v\n"
}
# it expects: True, $u = 2, $v = 2
In the above example, the increment ++ operators has the meaning to show you if an expression (like $v++ > 0) was evaluated or not.

You can use a short-circuit operator without the involving of a conditional statement. See the next short example:

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my ($u, $v) = (1);
defined $v || print "\$u = 1\n";
# it prints: $u = 1
Here, the condition defined $v is false so Perl will continue with the evaluating of the second operand and the print statement will be executed.

Another short-circuit operator is AND (&&).

The binding operator =~ binds a string expression to a pattern match. The string which is intended to bind is put on the left meanwhile the operator itself is put on the right. We use the pattern binding operator in the case we have a string which is not stored in the $_ variable and we need to perform some matches or substitutions of that string.

The following example shows you how to use Perl if statement with the regular expression match operator m// and the binding operator =~. To make the regex match case insensitive, I added the /i modifier.

#!/usr/local/bin/perl
 
use strict;
use warnings;
 
my $string = "This is the Perl language";
 
if ($string =~ m/perl/i) {
  print "word found\n";
}
else {
  print "word not found\n";
}
# it expects to print: word found
The expression ($string =~ m/perl/i) will return true if a match was found and false otherwise.
my $string = "Perl statements";
print ("match\n") if $string =~ m/^perl/i;
# it displays: match
Using the metacharacter ^ at the beginning of the pattern causes the word perl to be matched only if it occurs at the beginning of the $string. The /i modifier makes the search case insensitive.
my $string = "Perl statements";
print ("match\n") if $string =~ m/statements$/i;
# it displays: match
Using the metacharacter $ at the end of the pattern causes the word statements to be matched only if it occurs at the end of the $string. The /i modifier makes the search case insensitive.

You can use the | character (known as alternation) inside a pattern to match alternate patterns. See the following example:

my $string = "One simple statement";
if ($string =~ m/^(one|two|three|four)/i) {
  print "match\n";
}
The above pattern will match either one or two or three or four at the start of the $string. Because of the /i modifier, the match is case insensitive.
while (<STDIN>) {
  chomp;
  next if /^$/;
  # do something with the line; 
}
You can use both ^ and $ metacharacters to skip the empty lines read from STDIN. /^$/ returns true if the default $_ variable contains an empty line (there are not characters between the start and the end of the line). If the line read is empty, the next statement will reiterate the while loop by reading another line. If you don’t use the chomp function to remove the trailing newline, the above code will work too, because the metacharacter $ occurs just before the newline character, and the /^$/ pattern will match both "" and "\n".

The Perl language is well-known for its powerful text processing flexibility. The if statement is very useful to test if a pattern can match a string. The typical way to do this is by using the regular expression operator m// and the binding operator =~, as in the following example:

if ($string =~ m/pattern/) {
  print 'match';
} else {
  print 'no match';
}
The =~ binding operator it is used exclusively for pattern matching and returns true if the pattern was found in the $string and false otherwise. As an alternative, if you prefer, you can use the binding not operator !~ too, in a similar syntax:
 
if ($string !~ m/pattern/) {
  print 'no match';
} else {
  print 'match';
}
The !~ is the logical not version of =~ and it returns true only if the pattern is not found in the $string.

If you not use =~ or !~ in pattern matching, than it is assumed that your string was previously assigned to $_ and you can use the if statement and the match operator as in the following example:

print ('match') if m/pattern/;
Here m/pattern/ returns true if the pattern was found in $_ and false otherwise.

Sometimes finding patterns in strings is not enough and you need to modify the strings. One way is to use the substitution operator s///. The code below shows you how to use the Perl if statement to check if a substitution succeeded.

See the code:

my $string = "One simple statement";
if ($string =~ s/Simple/complex/i) {
  print "$string\n";
}
# it prints: One complex statement
 
if ($string =~ s/perl/php/i) {
  print "$string\n";
  # this code isn't reached
}
The expression $string =~ s/Simple/complex/i will change the word simple to complex and it will return true (the word Simple is matched because of the /i case insensitive modifier).

The expression $string =~ s/perl/php/i returns false because the word perl does not appear in the $string, so the $string will not be printed.