vkk05
vkk05

Reputation: 3222

String matching in Perl for multiple patterns

I have a string, and when I check it against with the variable its not giving me expected result. By using pattern matching mechanism it works fine.

Is this expected behavior in Perl. If not, how to resolve this without using pattern matching.

Code Below:

#!/usr/bin/perl

use strict; 
use warnings;

my $day_of_week = "Monday";

if (($day_of_week ne "Monday") or ($day_of_week ne "Tuesday")){
    print "In If. Today is $day_of_week.\n";
} else {
    print "In else part\n";
}

This should give output as:

In else part

But its giving me:

In If. Today is Monday.

When I change the if condtion with pattern matching like below, it works fine.

if ($day_of_week !~ /Monday|Tuesday) {

My concern is why the string matching is not working as per the condition. Am I doing something wrong here.

Upvotes: 3

Views: 928

Answers (2)

zdim
zdim

Reputation: 66883

It's the convoluted composite condition that got you --

$day_of_week ne "Monday"  # FALSE but 
$day_of_week ne "Tuesday" # TRUE

so you're testing

if (FALSE or TRUE)  #--> true

That's why it's recommended to try to always "straighten" those conditions.

So to test that it's neither Monday nor Tuesday

if ( $day_of_week ne "Monday" and $day_of_week ne "Tuesday" )

This is much harder to get confused.


The logic you probably meant need be encoded as

if (not ($day_of_week eq "Monday" or $day_of_week eq "Tuesday") )

Forming one large composite condition that is then negated is often clearer than the alternative, but not in this case in my opinion.

Upvotes: 5

ikegami
ikegami

Reputation: 385657

The following is always true:

it isn't Monday, OR it isn't Tuesday

  • On Monday, it isn't Tuesday, so it's true (F OR T = T)
  • On Tuesday, it isn't Monday, so it's true (T OR F = T)
  • On Wednesday, it's neither (T OR T = T)

You want

it isn't Monday, AND it isn't Tuesday

if ($day_of_week ne "Monday" && $day_of_week ne "Tuesday") {
    print "Today is $day_of_week.\n";
} else {
    print "Otherwise\n";
}

or

if ($day_of_week eq "Monday" || $day_of_week eq "Tuesday") {
    print "Otherwise\n";
} else {
    print "Today is $day_of_week.\n";
}

When I change the if condtion with pattern matching like below, it works fine.

That's because

it isn't Monday or Tuesday

isn't the same thing as

it isn't Monday, or it isn't Tuesday

We can prove this.

$day_of_week !~ /Monday|Tuesday/

is equivalent to

!( $day_of_week =~ /Monday|Tuesday/ )

which is equivalent to

!( $day_of_week =~ /Monday/ || $day_of_week =~ /Tuesday/ )

which is equivalent to

!( $day_of_week =~ /Monday/ ) && !( $day_of_week =~ /Tuesday/ )

(as per De Morgan's law)

which is equivalent to

$day_of_week !~ /Monday/ && $day_of_week !~ /Tuesday/

Notice how AND is used, but you used OR.

Upvotes: 2

Related Questions