pasja
pasja

Reputation: 365

How does split inside map work?

Yesterday I wrote a little subroutine to parse my /etc/hosts file and get the hostnames from it.

This is the subroutine:

sub getnames {
    my ($faculty, $hostfile) = @_;
    open my $hosts ,'<', $hostfile;
    my @allhosts = <$hosts>;
    my $criteria = "mgmt." . $faculty;
    my @hosts = map {my ($ip, $name) = split; $name} grep {/$criteria/} @allhosts; # <-this line is the question              
    return @hosts;
}

I called it like getnames('foo','/etc/hosts') and got back the hostnames that match the mgmt.foo regex.

The question is, why do I have to write $name alone in the map expression? If I don't write it, get back the whole line. Does the variable evaluate to its value?

Upvotes: 2

Views: 244

Answers (1)

Greg Bacon
Greg Bacon

Reputation: 139431

The list-context result from map is a concatenation of all the results of evaluating your block for each matching host. Remember that the return value from a block is the value of the last expression evaluated, whether or not your code incants an explicit return. Without the final $name, the last expression—and thus the block’s return value—is the result from split.

Another way to write it is

my @hosts = map {(split)[1]} grep {/$criteria/} @allhosts;

You could fuse the map and grep to get

my @hosts = map { /$criteria/ ? (split)[1] : () } @allhosts;

That is, if a given host meets your criteria, then split it. Otherwise, there is no result for that host.

Upvotes: 8

Related Questions