Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

How To Read Hosts File Into a Hash

by at2marty (Novice)
on Sep 15, 2011 at 23:00 UTC ( [id://926255]=perlquestion: print w/replies, xml ) Need Help??

at2marty has asked for the wisdom of the Perl Monks concerning the following question:

Here is what I am trying to do. I want to open the hosts file on my machine (Linux) and read the first two columns into a hash that will give me the ip address as the key, and the hostname as the value.

I've done some googling on the subject, and can't seem to find a clear answer.

I can read the contents of the hosts file into an array with no problem, but can't seem to get a good grasp of how to do so into a hash.

Here is an example of one of the things that I tried.

#!/usr/bin/perl -w use strict; my $hostfile = "/etc/hosts"; my %hosts = (); open FILE, "<", "$hostfile" || die "Cannot open $hostfile $!"; while (<FILE>) { chomp; my ($key, $value) = split (" ", $_); $hosts{$key} = $hosts{$value}; } close FILE;

Replies are listed 'Best First'.
Re: How To Read Hosts File Into a Hash
by onelesd (Pilgrim) on Sep 15, 2011 at 23:26 UTC
    You were close.
    while (<FILE>) { next if /^\s*#/ ; # skip comments chomp; my ($key, $value) = split (/\s+/, $_); $hosts{$key} = $value; # here was your mistake }

      Keep in mind that each line in the hosts file can define multiple aliases:

      #!/usr/bin/env perl use strict; use warnings; use Data::Dump qw/dump/; my $hostfile = "/etc/hosts"; my %hosts = (); open FILE, "<", "$hostfile" || die "Cannot open $hostfile $!"; while (<FILE>) { next if /^\s*#/ ; # skip comments chomp; my ($key, $values) = split /\s+/, $_, 2; my @values = split /\s+/, $values; $hosts{$key} = \@values; } print dump(\%hosts), $/; __END__ { "127.0.0.1" => ["localhost.localdomain", "localhost"], "127.2.3.4" => ["app.example.com"], "127.2.3.5" => ["www.example.com", "www", "web", "catalyst"], "127.2.3.6" => ["cisco.example.com", "router"], "127.2.3.7" => ["mail", "mail.example.com", "mx1"], }

      Thank you for your reply. I changed my code to the following.

      #!/usr/bin/perl -w use strict; my $hostfile = "/etc/hosts"; my %hosts = (); open FILE, "<", "$hostfile" || die "Cannot open $hostfile $!"; while (<FILE>) { next if /^\s*#/ ; # skip comments chomp; my ($key, $value) = split (" ", $_); $hosts{$key} = $value; } close FILE;

      The output is as follows.

      Use of uninitialized value $key in hash element at hash.pl line 14, <F +ILE> line 3. Use of uninitialized value $key in hash element at hash.pl line 14, <F +ILE> line 11.

      Why do I get the "uninitialized error" for $key?

        Why do I get the "uninitialized error" for $key?
        My guess is your input file has a blank line:
        while (<FILE>) { next if /^\s*#/ ; # skip comments next unless /\S/; # skip blank lines chomp; my ($key, $value) = split; $hosts{$key} = $value; }
        See perlre

        Your /etc/hosts file lines 3 and 11 have zero or more white space characters and nothing else. You should skip those:

        while (<FILE>) { next if /\A\s*\z/ ; # skip blank lines next if /^\s*#/ ; # skip comments

        Or combine the regexes:

        next if /\A\s*(?:#|\z)/ ; skip comments and blank lines
Re: How To Read Hosts File Into a Hash
by jwkrahn (Abbot) on Sep 16, 2011 at 00:58 UTC
    open FILE, "<", "$hostfile" || die "Cannot open $hostfile $!";

    You shouldn't quote variables like that:

    What's wrong with always quoting "$vars"?

    The high precedence of the || operator means that die will only execute if $hostfile contains the string "" or the string "0".    You need to either use parentheses with open:

    open( FILE, "<", $hostfile ) || die "Cannot open $hostfile $!";

    Or use the low precedence or operator:

    open FILE, "<", $hostfile or die "Cannot open $hostfile $!";


    while (<FILE>) { chomp; my ($key, $value) = split (" ", $_); $hosts{$key} = $hosts{$value}; }

    That should probably be:

    while (<FILE>) { my ($key, $value) = split; $hosts{$key} = $value; }

    Or if you want all the hosts associated with each IP address:

    while (<FILE>) { my ($key, @values) = split; push @{$hosts{$key}} = @values; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://926255]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2025-03-26 07:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When you first encountered Perl, which feature amazed you the most?










    Results (67 votes). Check out past polls.

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.