3
votes

I am reading data in from a YAML file (use YAML qw/LoadFile/). I need to be able to read the values and insert them into other files.

The YAML file is in this format:

--- 
host:
  - name: first_host
    interface:
      - name: eth0
        oldip: 1.2.3.4
        newip: 2.3.4.5
        oldgw: 1.2.3.1
        newgw: 2.3.4.1
      - name: eth1
        oldip: 1.2.3.4
        newip: 2.3.4.5
        oldgw: 1.2.3.1
        newgw: 2.3.4.1
      - name: eth2
        oldip: 1.2.3.4
        newip: 2.3.4.5
        oldgw: 1.2.3.1
        newgw: 2.3.4.1

If I run this through Data::Dumper I get the following ($Data::Dumper::Terse is enabled):

{
  'host' => [
            {
              'interface' => [
                             {
                               'oldgw' => '1.2.3.1',
                               'newgw' => '2.3.4.1',
                               'name' => 'eth0',
                               'newip' => '2.3.4.5',
                               'oldip' => '1.2.3.4'
                             },
                             {
                               'oldgw' => '1.2.3.1',
                               'newgw' => '2.3.4.1',
                               'name' => 'eth1',
                               'newip' => '2.3.4.5',
                               'oldip' => '1.2.3.4'
                             },
                             {
                               'oldgw' => '1.2.3.1',
                               'newgw' => '2.3.4.1',
                               'name' => 'eth2',
                               'newip' => '2.3.4.5',
                               'oldip' => '1.2.3.4'
                             }
                           ],
              'name' => 'first_host'
            },
            ]
}

I need to make changes, for instance in /etc/sysconfig/network-scripts/ifcfg-eth0, swapping the oldip value with the newip value. However, I'm coming up short on how to put it to use. If I just print the value of the loaded YAML file it appears to be nothing more than a hash reference. But, if I try to dereference the hash I get the following:

Reference found where even-sized list expected

This is followed by the hash reference.

This is the script that I'm starting with:

#!/usr/bin/perl

use strict;
use warnings;
use YAML qw(LoadFile);
use Data::Dumper;
$Data::Dumper::Terse = 1;

my %data = LoadFile("/home/user/bin/perl/dummy_data.yml");

print \%data

Can someone explain to me what I need to do to be able to read the values from this input so I can make the changes I need to make?

1
You may want to look at perlreftut and perlref.Brad Gilbert

1 Answers

11
votes

LoadFile is returning a hashref, not a hash. The difference is subtle but important.

You have the option of using the hashref as it is:

my $data = LoadFile("data.yml");
print $data;

Or you can cast it into a hash:

my %data = %{ LoadFile("data.yml") };
print %data;

You can handle the reference however you like, just as long as you know what it is.

You do access elements a little differently:

$data{'foo'}   #hash %data
$data->{'foo'} #hashref $data

You may notice subs tend to expect hash references instead of hashes, sometimes. That's usually how people first come across them.