3

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?

theillien
  • 1,189
  • 3
  • 19
  • 33
  • You may want to look at [perlreftut](http://perldoc.perl.org/perlreftut.html "perldoc perlreftut") and [perlref](http://perldoc.perl.org/perlref.html "perldoc perlref"). – Brad Gilbert Aug 25 '13 at 01:53

1 Answers1

11

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.

Community
  • 1
  • 1
rutter
  • 11,242
  • 1
  • 30
  • 46
  • I seem to be getting the hang of it. It appears that every level is another reference either to an array or to another hash. So far I've been able to print out more and more of the data structure by dereferencing them as I delve deeper into it. – theillien Aug 24 '13 at 00:27