bhushanQA has asked for the wisdom of the Perl Monks concerning the following question:

I have below code to read the parameters and section from my .ini file, but output is not in order. code:
my $config = Config::Tiny->read('SQLdata.ini'); foreach my $section (keys %$config) { print "[$section]\n"; foreach my $parameter (keys %{$config->{$section}}) { print "$parameter = $config->{$section}->{$par +ameter}\n"; } #return $parameter; }
SQLdata.ini has below sections and parameters:
[insert] SQL1 = insert into table <table1> SQL2 = insert into table <table2> SQL3 = insert into table <table3> SQL4 = insert into table <table4> [Truncate] SQL1= truncate table <tablename1> SQL2= truncate table <tablename2> [update] SQL1 = update into <table1> SQL2 = update into <table2> output is: [Truncate] SQL2= truncate table <tablename2> SQL1= truncate table <tablename1> [insert] SQL4 = insert into table <table4> SQL2 = insert into table <table2> SQL3 = insert into table <table3> SQL1 = insert into table <table1> [update] SQL2 = update into <table2> SQL1 = update into <table1>
how can I achieve output in order??

Replies are listed 'Best First'.
Re: Parameters not in order by using Config::Tiny
by Corion (Patriarch) on Jul 06, 2015 at 13:07 UTC
Re: Parameters not in order by using Config::Tiny
by GotToBTru (Prior) on Jul 06, 2015 at 13:12 UTC

    UPDATE: never mind! Better choice of module as suggested by Corion will solve this issue.

    Hashes don't store their keys in order, so that's why (keys %...) returns them in a way you don't expect. For the inner case, replace

    (keys %{$config->{$section}})

    with

    (sort keys %{$config->{$section}}

    For the outer loop, perhaps store the sections in array instead of a hash?

    Dum Spiro Spero
      This "(sort keys %{$config->{$section}}" has solved my problem .. Thanks a lot :) good solution
Re: Parameters not in order by using Config:Tiny
by 1nickt (Canon) on Jul 06, 2015 at 14:26 UTC

    Hm, I am not sure why you would need them to be ordered.

    You might want to order them during development so you could print and check to see that Config::Tiny is in fact processing your file properly, but in your program you should not be using them in a list anyway --- the whole point of an .ini file is to have named parameters ... so that you can avoid having to remember the order and having to use your params in order.

    After you have tested, you will want to use Config::Tiny to slurp in your named parameters, and then just use them as you need them:

    # in ini file [Section1] foo=bar baz=quux [Section2] perl=cool
    # in program after reading file with Config::Tiny # note you can use them in any order you want my $perl = $ini->{'Section2'}->{'perl'}; my $baz = $ini->{'Section1'}->{'baz'}; my $foo = $ini->{'Section1'}->{'foo'};

    Please state your reason for needing to sort your config parameters if this doesn't make sense to you.

    Remember: Ne dederis in spiritu molere illegitimi!

      I think this requirement comes from the code in 1133314:

      foreach $ini_sect ( keys %ini_file ) { %$ini_sect = %{ $ini_file{$ini_sect} }; }

      This builds up a common structure from information distributed across different sections. I use a similar approach to have "common" and "specialized" sections:

      [GENERAL] FOO=bar TEMPLATE=./templates/mytemplate-v3.html [until-20150409] TEMPLATE=./templates/mytemplate-v2.html [until-20150307] TEMPLATE=./templates/mytemplate-v1.html

        OK, so you have options for your options based on things, like maybe the date. I must be dense today, but I can't see how sorting would help unless you have cleverly named your sections (as in your example) and then do:

        my $template; while ( I am looping through Sections) { next unless first half of name is 'until'; next unless date in second half of name hasn't passed yet; $template = this_Section->{TEMPLATE}; last; }

        But for the OP, how would

        foreach $ini_sect ( sort keys %ini_file ) { %$ini_sect = %{ $ini_file{$ini_sect} }; }

        be any better than

        foreach $ini_sect ( keys %ini_file ) { %$ini_sect = %{ $ini_file{$ini_sect} }; }

        ??

        Remember: Ne dederis in spiritu molere illegitimi!
Re: Parameters not in order by using Config::Tiny
by marioroy (Prior) on Jul 06, 2015 at 17:09 UTC

    I was not aware of Tiny::Config::Ordered until today. However, the Hash::Ordered module v0.009 is quite nice IMO.

    The following diff is all that's needed to preserve order transparently in Tiny::Config.

    $ diff -u Tiny.pm.orig Tiny.pm --- Tiny.pm.orig 2015-07-06 12:51:54.000000000 -0400 +++ Tiny.pm 2015-07-06 13:02:22.000000000 -0400 @@ -3,6 +3,7 @@ # If you thought Config::Simple was small... use strict; +use Hash::Ordered; # Warning: There is another version line, in t/02.main.t. @@ -39,7 +40,8 @@ # Create an object from a string sub read_string { my $class = ref $_[0] ? ref shift : shift; - my $self = bless {}, $class; + tie my %obj, 'Hash::Ordered'; + my $self = bless \%obj, $class; return undef unless defined $_[0]; # Parse the file @@ -59,7 +61,10 @@ # Create the sub-hash if it doesn't exist. # Without this sections without keys will not # appear at all in the completed struct. - $self->{$ns = $1} ||= {}; + $self->{$ns = $1} ||= do{ + tie my %obj, 'Hash::Ordered'; + \%obj; + }; next; }

    The output order matches the ini file (sections and elements).

    $ perl test.pl [insert] SQL1 = insert into table <table1> SQL2 = insert into table <table2> SQL3 = insert into table <table3> SQL4 = insert into table <table4> [Truncate] SQL1 = truncate table <tablename1> SQL2 = truncate table <tablename2> [update] SQL1 = update into <table1> SQL2 = update into <table2>

    I sent the link to the first post to both authors.

    Kind regards, Mario

      Thanks all for the help.. the best solution found by using 'sort' keyword.. which makes my job easy...and its working perfectly..however I have gone through the other solutions as well.. Appreciate.. right now I don't want to change my logic which is working and printing all section and parameter in order.  use Config::Tiny::Ordered; this is quite helpful.