There is a strange scalar variable called $_ in Perl, which is the default variable, or in other words the topic.

In Perl, several functions and operators use this variable as a default, in case no parameter is explicitly used. In general, I'd say you should NOT see $_ in real code. I think the whole point of $_ is that you don't have to write it explicitly.

Well, except when you do.

Having a default variable is a very powerful idea, but using it incorrectly can reduce the readability of your code.

Check out this script:

use strict;
use warnings;
use v5.10;

while (<STDIN>) {
   chomp;
   if (/MATCH/) {
      say;
   }
}

This is exactly the same as:

use strict;
use warnings;
use v5.10;

while ($_ = <STDIN>) {
   chomp $_;
   if ($_ =~ /MATCH/) {
      say $_;
   }
}

I would never write the second one, and I'd probably write the first one only in a very small script, or in a very tight part of the code.

Maybe not even there.

As you can see, in a while loop, when you read from a file handle, even if that's the standard input, if you don't assign it explicitly to any variable, the line that was read will be assigned to $_.

chomp() defaults to work on this variable, if no parameter was given.

Regular expression matching can be written without an explicit string, and even without the =~ operator. If written that way, it will work on the content of $_.

Finally say(), just as print(), would print the content of $_, if no other parameter was given.

split

The second parameter of split is the string to be cut in pieces. If no second parameter is given, split will cut up the content of $_.

my @fields = split /:/;

foreach

If we don't supply the name of the iterator variable to foreach, it will use $_.

use strict;
use warnings;
use v5.10;

my @names = qw(Foo Bar Baz);
foreach (@names) {   # puts values in $_
    say;
}

Assignment in condition

There are some cases when we implicitly use $_ by mistake.

Some experts might use this kind of code deliberately, but when this is written by a newbie, or a mere mortal, it is just a bug.

if ($line = /regex/) {
}

You see, instead of the regex operator: =~ we used here the plain assignment operator: =. This is, in fact the same as

if ($line = $_ =~ /regex/) {
}

It takes the content of $_, executes the pattern matching on it, and assigns the result to $line. Then checks if the content of $line is true or false.

Explicit $_

I mentioned earlier I recommend not using $_ explicitly. Sometimes I see people writing code like this:

while (<$fh>) {
  chomp;
  my $prefix = substr $_, 0, 7;
}

I think, once you use a statement in perl that forces you to explicitly write out $_, such as substr in our case, you should go all the way and use a more meaningful name. Even if that means more typing:

while (my $line = <$fh>) {
  chomp $line;
  my $prefix = substr $line, 0, 7;
}

Another bad example I often see:

while (<$fh>) {
   my $line = $_;
   ...
}

This probably happens to people who do not understand the interaction between the while statement, the read operator on the file handle and $_.

This could be written in a more simple way directly assigning to the $line variable.

while (my $line = <$fh>) {
   ...
}

Exceptions

There are several cases where you can't really avoid, and you have to use $_ explicitly. These are the grep and map function, and the other similar ones, such as any.