Search code examples
perlinignu-coreutils

Read ini files without section names


I want to make a configuration file which hold some objects, like this (where of course none of the paramaters can be considered as a primary key)

param1=abc
param2=ghj

param1=bcd
param2=hjk
; always the sames parameters

This file could be read, lets say with Config::IniFiles, because it has a direct transcription into ini file, like this

[0]
param1=abc
param2=ghj

[1]
param1=bcd
param2=hjk

with, for example, something like

perl -pe 'if (m/^\s*$/ || !$section ) print "[", ($section++ || 0) , "]"'

And finish with

open my $fh, '<', "/path/to/config_file.ini" or die $!;
$cfg = Config::IniFiles->new( -file => $fh );
(...parse here the sections starting with 0.)

But, I here ask me some question about the thing becoming quite complex....

(A) Is There a way to transform the $fh, so that it is not required to execute the perl one-liner BEFORE reading the file sequentially? So, to transform the file during perl is actually reading it.

or

(B) Is there a module to read my wonderfull flat database? Or something approching? I let myslef said, that Gnu coreutils does this kind of flat file reading, but I cannot remember how.


Solution

  • You can create a simple subclass of Config::INI::Reader:

    package MyReader;
    
    use strict;
    use warnings;
    
    use base 'Config::INI::Reader';
    
    sub new {
        my $class = shift;
        my $self = $class->SUPER::new( @_ );
    
        $self->{section} = 0;
    
        return $self;
    }
    
    
    sub starting_section { 0 };
    
    sub can_ignore { 0 };
    
    sub parse_section_header {
         my ( $self, $line ) = @_;
    
        return $line =~ /^\s*$/ ? ++$self->{section} : undef ;
    }
    
    1;
    

    With your input this gives:

    % perl -MMyReader -MData::Dumper -e 'print Dumper( MyReader->read_file("cfg") )'
    $VAR1 = {
              '1' => {
                       'param2' => 'hjk',
                       'param1' => 'bcd'
                     },
              '0' => {
                       'param2' => 'ghj',
                       'param1' => 'abc'
                     }
            };