读取没有部分名称的ini文件

时间:2014-12-18 13:22:10

标签: perl ini gnu-coreutils

我想创建一个包含某些对象的配置文件,如此(当然,没有一个参数可以被视为主键)

param1=abc
param2=ghj

param1=bcd
param2=hjk
; always the sames parameters

这个文件可以被读取,让我们说Config::IniFiles,因为它有直接转录到ini文件,就像这样

[0]
param1=abc
param2=ghj

[1]
param1=bcd
param2=hjk

,例如

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

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

但是,我在这里问了一些关于事情变得相当复杂的问题......

(A)有没有办法转换$ fh,以便在顺序读取文件之前不需要执行perl单行程序?因此,在perl期间转换文件实际上是在阅读它。

(B)是否有一个模块可以阅读我的精彩数据库?或者是什么东西?我让myslef说,Gnu coreutils会做这种平面文件阅读,但我不记得是怎么做的。

4 个答案:

答案 0 :(得分:1)

您可以使用变量引用而不是文件名来创建从中读取的文件句柄:

use strict;
use warnings;
use autodie;

my $config = "/path/to/config_file.ini";

my $content = do {
  local $/;
  open my $fh, "<", $config;
  "\n". <$fh>;
};

# one liner replacement
my $section = 0;
$content =~ s/^\s*$/ "\n[". $section++ ."]" /mge;

open my $fh, '<', \$content;
my $cfg = Config::IniFiles->new( -file => $fh );
# ...

答案 1 :(得分:1)

您可以将修改后的数据存储在真实文件或字符串变量中,但我建议您通过设置输入记录分隔符 {{1}来使用段落模式到空字符串。喜欢这个

$/

<强>输出

use strict;
use warnings;

{
  local $/ = '';  # Read file in "paragraphs"
  my $section = 0;
  while (<DATA>) {
    printf "[%d]\n", $section++;
    print;
  }
}

__DATA__
param1=abc
param2=ghj

param1=bcd
param2=hjk

<强>更新

如果您将文件读入字符串,如上所述添加节标识符,则可以使用字符串引用将结果直接读入[0] param1=abc param2=ghj [1] param1=bcd param2=hjk 对象,例如

Config::IniFiles

此示例显示 tie 接口,该接口生成包含配置信息的Perl哈希。我只使用my $config = Config::IniFiles->new(-file => \$modified_contents) 来显示结果哈希的结构。

Data::Dump

<强>输出

use strict;
use warnings;

use Config::IniFiles;

my $config;
{
  open my $fh, '<', 'config_file.ini' or die "Couldn't open config file: $!";
  my $section = 0;
  local $/ = '';
  while (<$fh>) {
    $config .= sprintf "[%d]\n", $section++;
    $config .= $_;
  }
};

tie my %config, 'Config::IniFiles', -file => \$config;

use Data::Dump;
dd \%config;

答案 2 :(得分:1)

您可以创建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;

根据您的输入,这会给出:

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

答案 3 :(得分:0)

您可能希望对一系列对象(如Powershell)执行操作,而不是文本流,因此

use strict; 
use warnings; 
use English;

sub operation {
    # do something with objects
    ...
}

{
local $INPUT_RECORD_SEPARATOR = '';
# object are separated with empty lines
while (<STDIN>) {
    #                  key       value
    my %object = ( m/^ ([^=]+) = ([[:print:]]*) $ /xmsg ); 
    # key cannot have = included, which is the delimiter
    # value are printable characters (one line only) 
    operation ( \%object )  
} 

也像其他答案一样。