Domanda

I am using perl script to update sections in conf file . my script i working properly but when i execute script the ordered on sections changed automatically while i dont want to change the order.script is following .

#!/usr/bin/perl
use Config::Tiny;
$file = 'sss.conf';
my $Config = Config::Tiny->new;
$Config = Config::Tiny->read( $file );
my $rootproperty = $Config->{_}->{rootproperty};
$Config->{amrit}->{host} = 'Not Bar!';
$Config->write( $file );

and file contents following line;

[amrit]
type=friend
host=111.118.253.145
port=2776
username=amrit
secret=password
disallow=all
allow=gsm
context=sip-calling
qualify=yes
call-limit=22

Please help me here i dont want to change order of fields

È stato utile?

Soluzione

From the documentation for Config::Tiny:

...Config::Tiny does not preserve your comments, whitespace, or the order of your config file. See Config::Tiny::Ordered (and possibly others) for the preservation of the order of the entries in the file.

So, do as the documentation suggests, and see Config::Tiny::Ordered.

Update: Based on the comments I'll try to provide additional help here.

First, your existing script is mostly just a copy-paste from the Config::Tiny synopsis, without any deep understanding of what most of it does. The relevant parts... or at least those parts you should keep are:

use Config::Tiny;
$file = 'sss.conf';
$Config = Config::Tiny->read( $file );
$Config->{amrit}->{host} = 'Not Bar!';
$Config->write( $file );

If you add use Data::Dumper; at the top of the script, and immediately after reading the config file you add print Dumper $Config;, the structure would look like this:

{
    'amrit' => {
        'call-limit' => '22',
        'host' => '111.118.253.145',
        'secret' => 'password',
        'context' => 'sip-calling',
        'port' => '2776',
        'username' => 'amrit',
        'allow' => 'gsm',
        'qualify' => 'yes',
        'type' => 'friend',
        'disallow' => 'all'
    }
}

Modifying the structure with the script I've posted above would work if you don't mind the key/value pairs to have their orders rearranged. But you need to preserve order. So the suggestion was to switch to Config::Tiny::Ordered. That module preserves order by rearranging the structure differently. If you change the script to look like this:

use Data::Dumper;
use Config::Tiny::Ordered;
$file = 'conf.conf';
$Config = Config::Tiny->read( $file );
print Dumper $Config;

You will see that the structure now looks like this:

{
    'amrit' =>
  [
    {
      'value' => 'friend',
      'key' => 'type'
    },
    {
      'key' => 'host',
      'value' => '111.118.253.145'
    },
    {
      'value' => '2776',
      'key' => 'port'
    },
    {
      'value' => 'amrit',
      'key' => 'username'
    },
    {
      'value' => 'password',
      'key' => 'secret'
    },
    {
      'value' => 'all',
      'key' => 'disallow'
    },
    {
      'key' => 'allow',
      'value' => 'gsm'
    },
    {
      'key' => 'context',
      'value' => 'sip-calling'
    },
    {
      'key' => 'qualify',
      'value' => 'yes'
    },
    {
      'value' => '22',
      'key' => 'call-limit'
    }
  ]
}

Or in other words, the internal structure of the Config::Tiny::* object has changed from a hash of hashes, to a hash of arrays of hashes. ("All problems in computer science can be solved by another level of indirection" -- David Wheeler) This change in the shape of the datastructure exists to move away from the problem of hashes being unordered containers.

So now instead of convenient hash lookups for the key named "host", you have to iterate through your structure to find the array element that has an anonymous hash with a key field named host. More work:

use List::Util qw(first);
use Config::Tiny::Ordered;
$file = 'sss.conf';
$Config = Config::Tiny::Ordered->read( $file );
my $want_ix = first {
  $Config->{amrit}[$_]{key} eq 'host'
} 0 .. $#{$Config->{amrit}};
$Config->{amrit}[$want_ix]{value} = 'Not Bar!';
$Config->write( $file );

This works by running through the amrit section of the config file looking for the element in the structure's anonymous array that has an anonymous hash with a field named 'key', and once that array element is found, modifying the 'value' hash element to 'Not Bar!'

If this is a one time thing for you, you're done. If you want to be able to do it yourself next time, read perldoc perlreftut, perldoc perldsc, as well as documentation for any of the functions used herein that aren't immediately clear.

Altri suggerimenti

From the CPAN page:

Lastly, Config::Tiny does not preserve your comments, whitespace, or the order of your config file.

Use COnfig::Tiny::Ordered instead

See Config::Tiny::Ordered (and possibly others) for the preservation of the order of the entries in the file.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top