views:

81

answers:

3

Hello! On http://sial.org/howto/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?

+5  A: 

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.

Dave Sherohman
+1  A: 

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

justintime
+4  A: 

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  

See not in perldoc perlop:

Unary not returns the logical negation of the expression to its right. It's the equivalent of ! except for the very low precedence.

Sinan Ünür