How does the different behavior of the unless- and “if !” statement influence the range-operator in scalar context?
-
25-09-2019 - |
문제
On http://novosial.org/perl/one-liner/ I found the following two one-liners. The outputs are different because the unless
statement is different from if !
( due to the associativity and precedence rules ).
cat file: foo bar
perl -ne 'print unless /^$/../^$/' file foo bar
perl -ne 'print if ! /^$/../^$/' file foo bar
How does the different behavior of the if !
-statement make the second one-liner output one blank line?
해결책
As the linked article says, it's a matter of associativity and precedence...
print unless /^$/../^$/
is equivalent to print if !(/^$/../^$/)
print if ! /^$/../^$/
is equivalent to print if (!/^$/)../^$/
Note that the first negates the range expression, while the second negates the range's beginning condition, but not the range itself.
다른 팁
The answer, IMHO, is that there is no if !
statement in Perl: There is an if
statement and there is a !
operator. The !
operator does not bind to if
; it operates on its argument. If you start thinking in these terms, your life will be easier.
So, in your case, you have,
do_something() unless something;
and
do_something() if something-else;
Let's put in the normally invisible parentheses:
do_something() unless ( something );
and
do_something() if ( something-else );
In this case, you tried to write something-else
so that the truth value of that condition is equivalent to the truth of something
, but failed to take into account the fact that !
operator binds tightly.
That is why there is not
.
Try
perl -ne 'print if not /^$/../^$/' file
Unary
not
returns the logical negation of the expression to its right. It's the equivalent of!
except for the very low precedence.
The range test will return true up to the time that the 2nd operand is true. It will then return false on the next call.
This snippet tells us what the range operator is returning
perl -ne "$x= ( ! /^$/../^$/ ) ; print qq/$x : $_/" range_test.TXT
which produces
1 : foo
2E0 :
:
:
1 : bar
So the first blank line generates a true response, the next one false