linux - 使用 perl 更新 Conf 文件

标签 linux perl perl-module

我正在使用 perl 脚本来更新 conf 文件中的部分。我的脚本工作正常,但是当我执行脚本时,各部分的顺序会自动更改,而我不想更改顺序。脚本如下。

#!/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 );

以及以下行的文件内容;

[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

请在这里帮助我,我不想更改字段的顺序

最佳答案

来自 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.

因此,请按照文档的建议进行操作,并查看 Config::Tiny::Ordered。

更新:根据评论,我将尝试在此处提供其他帮助。

首先,您现有的脚本大多只是从 Config::Tiny 概要中复制粘贴的内容,而对其大部分功能没有任何深入的了解。相关部分...或者至少您应该保留的部分是:

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

如果您在脚本顶部添加 use Data::Dumper;,并在读取配置文件后立即添加 print Dumper $Config;,结构将如下所示:

{
    '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'
    }
}

如果您不介意键/值对重新排列顺序,则可以使用我上面发布的脚本修改结构。但你需要维持秩序。因此建议切换到 Config::Tiny::Ordered。该模块通过以不同方式重新排列结构来保持顺序。如果将脚本更改为如下所示:

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

您将看到结构现在如下所示:

{
    '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'
    }
  ]
}

或者换句话说,Config::Tiny::* 对象的内部结构已经从哈希的哈希变成了哈希数组的哈希。 (“计算机科学中的所有问题都可以通过另一级间接解决”- David Wheeler)数据结构形状的这种变化是为了摆脱散列是无序容器的问题。

因此,现在您不必对名为“host”的键进行方便的哈希查找,而是必须迭代结构以查找具有名为 host 的键字段的匿名哈希的数组元素。更多工作:

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 );

其工作原理是运行配置文件的 amrit 部分,在结构的匿名数组中查找具有名为“key”字段的匿名哈希的元素,一旦找到该数组元素,将“value”哈希元素修改为“Not Bar!”

如果这对您来说只是一次性的事情,那么您就完成了。如果您希望下次能够自己完成此操作,请阅读 perldoc perlreftutperldoc perldsc 以及此处使用的任何尚不明确的函数的文档。

关于linux - 使用 perl 更新 Conf 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21772599/

相关文章:

regex - Perl:如何在对变量进行分组后插入数字?

perl - 是否有一个 perl 模块可以启动一个进程并将三个主要 I/O 句柄返回给该进程?

linux - bash 脚本昨天的 zip 文件

linux - 如何告诉 "gmake"使用另一个版本的 GCC? (Linux)

javascript - 将 html 页面中的 javascript 变量传递到 html 表单(在同一页面上)以提交给 perl cgi

perl 解析多个字符串的文件

perl:Log::Log4perl 可以在多线程环境中工作吗?

c++ - 使用 C++ 以毫秒为单位查找实时时间的好方法是什么?

linux - QEMU:两个MCU之间的USART通信(STM32)

json - 如何在 Perl 中将简单的哈希转换为 json?