Abhinav said:
Hmm ..
Reading this inside out, this would
1. check if $_ !~ /asd/
2. The return value from this check is taken an expression,
which is on the right side of $str
Hence, $str =~ expr # This is evaluated as $str =~ /expr/
This is what I could ascertain from "Programming Perl",
page 90, "Binding Operators". I hope I am correct ?
It looks like you are correct, Abhinav. According to the "Binding
Operators" section of "perldoc perlop", "if the right argument is an
expression rather than a search pattern [(or a substitution or
transliteration)] it is interpreted as a search pattern at run time."
So the code:
$str =~ "asd";
is just a sloppy way of saying:
$str =~ m/asd/;
It gets weirder, however. According to "perldoc perlop" in the
section "m/PATTERN/cgimosx", "if the PATTERN evaluates to the empty
string, the last
*successfully* matched regular expression is used instead."
Usually this isn't a major concern, but it is if the pattern
contains a variable that is set to the empty string. So how does that
affect you?
Well, by tinkering around with Perl's regular expression matching,
it seems that m/PATTERN/ either returns a 1 if the match was
successful, or "" (the empty string -- which evaluates to false) if
the match was unsuccessful. Putting a "!" in front of either will
return the other (in other words, ((!1) eq "") and ((!"") eq 1).
Therefore, the original line of code you posted:
$str =~ !/asd/;
is equivalent to:
$str =~ ! ($_ =~ m/asd/);
If $_ is either undefined or does not contain the string "asd",
then the line is also equivalent to:
$str =~ ! ("");
which is equivalent to:
$str =~ 1;
which is equivalent to:
$str =~ m/1/;
which will return true only if $str contains a "1".
On the other hand, if $_ is defined and contains the string "asd",
then the line:
$str =~ !/asd/;
which, as I already said, is equivalent to:
$str =~ ! ($_ =~ m/asd/);
is now equivalent to:
$str =~ ! (1);
which is equivalent to:
$str =~ "";
which is equivalent to:
$str =~ m//;
which, according to the perldoc, will not try to match an empty
string, but will use the last *successfully* matched regular
expression instead.
Therefore, if you see had lines of code:
"Wizard of Wor" =~ m/Wor/; # successful match
"All your base are belong to us" =~ m/bases/;
$_ = "wasderful";
$str = "Hello, World!";
$str =~ !/asd/; # original line
the line:
$str =~ !/asd/; # original line
will be equivalent to:
$str =~ m/Wor/;
because the m/Wor/ match was the last successful pattern match. It
will therefore evaluate to true, even though $str does not contain the
string "asd".
Strange, isn't it?
Maybe this bizzare side-effect helps explain why, as you said in
your first post, that the code worked in some cases. The original
line of code was meant to check for the non-existence of "asd", but
instead checked for the existence of "Wor". Either way, it's still
possible to evaluate to true in some cases (like the one I just showed
you).
I hope this explains things more than it confused you. To tell you
the truth, Abhinav, your question made me search through the Perl
documentation for a good while before I figured out what was
happening. In other words, a lot more was happening "behind the
scenes" with your code than I first realized!