Meaning of if(!$_)

Viewed 102

I have a script in Perl that is reading a file. At some point, the code utilize the following if statement inside a for loop:

for (my $i = 0; $i<10 ; $i++ ) {

    $_ = <INPUT>;
    if (!$_) {last;} 
    
...

I am new in Perl, so I would like to know the meaning of !$_. In this example, $_ is a line of my file. So, what content the line should have to the if statement be true.

1 Answers

The if condition, what is inside (), is evaluated in a boolean scalar context to be tested for "truthiness." So if it's undef or '' (empty string) or 0 (or string "0") it's false.

That ! negates what follows it, so if (!$_) is true if $_ is false (undef or '' or 0 or "0"). However, in this case that $_ is assigned from <> operator so it'll always have a linefeed at the end -- unless the source for <> was exhausted in which case <> returns undef.

So, in this case, that if (!$_) tests for whether there is nothing more to read from INPUT, and exits the for loop with last if that is the case.

A few comments on the shown code.

  • That C-style for loop can also be written as for my $i (0..9), what is considered far nicer and more readable.† See foreach, and really follow links for flow-control key-words

  • The piece of code

    $_=<INPUT>
    if (!$_) { last; }
    ...
    

    reads from INPUT filehandle and exits its loop (see last) once there is end-of-file. (That need not be an actual file but any resource readable via a filehandle.)

    This is clumsy, to say the least; a common way of doing it is

    while (<INPUT>) {
        ...
    }
    

† So much so that even hard-core compiled languages now have it. The C++11 introduced the range-based for loop

for (auto var: container) ...  // (really, const auto&), or auto&, or auto&&

and the standard reference linked above says

Used as a more readable equivalent to the traditional for loop [...]

Related