Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

How To Read Hosts File Into a Hash

by at2marty (Novice)
on Sep 15, 2011 at 23:00 UTC ( #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 (Monsignor) 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 making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2023-11-28 22:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?