Douglas
Douglas

Reputation: 389

Perl - reading in multi-line records from config file

I'm trying to read in a multi-line config file with records into a perl hash array

Example Config File:

    record_1
      phone=5551212
      data=1234234
    end_record_1

    record_2
      people_1=bob
      people_2=jim
      data=1234
    end_record_2

    record_3
     people_1=sue
    end_record_3

here's what I'm looking for:

$myData{1}{"phone"}  <--- 5551212
$myData{1}{"data"}   <--- 1234234

$myData{2}{"people_1"} <--- bob
... etc

What's the best way to read this in? Module? Regex with multi-line match? Brute force? I'm up in the air on where to head next.

Upvotes: 1

Views: 2187

Answers (3)

Charles Boyd
Charles Boyd

Reputation: 316

There are a number of modules for this, so the best practice is (as usual) to use them rather than re-invent the wheel.

From the snippet of the config file you posted, it looks like Config::Simple may be the best choice. If you can simplify the config format, then Config::Tiny would be easier to use. If things get more complicated, then you may have to use Config::General.

http://metacpan.org/pod/Config::Tiny

http://metacpan.org/pod/Config::Simple

http://metacpan.org/pod/Config::General

Upvotes: 1

Kenosis
Kenosis

Reputation: 6204

Here's one option with your data set:

use strict;
use warnings;
use Data::Dumper;

my %hash;
{
    local $/ = '';
    while (<DATA>) {
        my ($rec) = /record_(\d+)/;
        $hash{$rec}{$1} = $2 while /(\S+)=(.+)/g;
    }
}

print Dumper \%hash;

__DATA__
record_1
    phone=5551212
    data=1234234
end_record_1

record_2
    people_1=bob
    people_2=jim
    data=1234
end_record_2

record_3
    people_1=sue
end_record_3

Output:

$VAR1 = {
          '1' => {
                   'data' => '1234234',
                   'phone' => '5551212'
                 },
          '3' => {
                   'people_1' => 'sue'
                 },
          '2' => {
                   'people_1' => 'bob',
                   'data' => '1234',
                   'people_2' => 'jim'
                 }
        };

Setting local $/ = '' results in an empty line being treated as a "record separator" in your data set, so we can use regexs on those records to grab the information for the hash keys/values.

Hope this helps!

Upvotes: 8

paddy
paddy

Reputation: 63481

Read it in one line at a time.

When you see a new record, add a new empty associative array to myData and grab a reference to it - this will be your "current record".

Now when you see key/value pairs on a line, you can add that to the current record array (if there is one)

When you see the end of a record, you just clear the reference to the current record.

Upvotes: 0

Related Questions