PERL:读取配置文件中的不同块

时间:2014-01-26 11:20:35

标签: regex perl

我想阅读以下格式的配置文件我能够读取块名称,即字符串,buildid,major如何我无法 读取每个块的值,即values = 98的variables.buildid和文件的路径igd_version.h,readme以及类似的Major

[strings]
variables=BUILDID,MAJOR

[BUILDID]
VALUE=898
VERSION.H=/home/src/gd_version.h
readme=/home/src/readm.txt

[MAJOR]
VALUE=8
IGD2.H=/home/src/igd2.h
readme=/home/src/readm.txt
license=/usr/src/license.html

这是我的代码

  while (<INFILE>) {
    my $cfgLine = $_;
    next unless ($cfgLine =~ s/\[([^]]+)\]// ) ;
    my $header = $1;
    }

有些机构可以建议我任何想法,我已经通过cpan(config :: tiny,config :: simple)因为设计更改而无法通过。 这里“VALUE”是所有块和文件名的公共变量,块的文件数不同。 在这里我们如何将IGD2.h的值和其他文件名和路径分配给变量来验证文件的存在。

3 个答案:

答案 0 :(得分:2)

我同意使用上面提到的ini-parsing模块是可取的。不过,也许以下内容会有所帮助:

use strict;
use warnings;
use Data::Dumper;

my ( $block, %hash );

while (<DATA>) {
    $block = $1 if /\[(.+)\]/;
    $hash{$block}{$1} = $2 if /(\S+?)\s*=\s*(\S+)/ and defined $block;
}

print Dumper \%hash;
__DATA__
[strings]
variables=BUILDID,MAJOR

[BUILDID]
VALUE=898
VERSION.H=/home/src/gd_version.h
readme=/home/src/readm.txt

[MAJOR]
VALUE=8
IGD2.H=/home/src/igd2.h
readme=/home/src/readm.txt
license=/usr/src/license.html

输出:

$VAR1 = {
          'BUILDID' => {
                         'VERSION.H' => '/home/src/gd_version.h',
                         'VALUE' => '898',
                         'readme' => '/home/src/readm.txt'
                       },
          'MAJOR' => {
                       'VALUE' => '8',
                       'readme' => '/home/src/readm.txt',
                       'license' => '/usr/src/license.html',
                       'IGD2.H' => '/home/src/igd2.h'
                     },
          'strings' => {
                         'variables' => 'BUILDID,MAJOR'
                       }
        };

要访问单个值,请使用以下模式:

my $value = $hash{'block'}{'key'};

例如:

print $hash{'BUILDID'}{'VERSION.H'};

输出:

/home/src/gd_version.h

如果您想尝试不同的ini模块,Config::IniFiles将创建与上述相同的HoH:

use strict;
use warnings;
use Config::IniFiles;

tie my %hash, 'Config::IniFiles', ( -file => 'config.ini' );
print $hash{'BUILDID'}{'VERSION.H'};

输出:

/home/src/gd_version.h

如果您不知道ini文件的内容,但仍想访问这些值,则可以执行以下操作 - 给出上面的HoH:

for my $block ( keys %hash ) {
    print "$block:\n";
    for my $key ( keys %{ $hash{$block} } ) {
        print "$key => $hash{$block}{$key}\n";
    }

    print "\n";
}

输出:

BUILDID:
VERSION.H => /home/src/gd_version.h
VALUE => 898
readme => /home/src/readm.txt

MAJOR:
VALUE => 8
readme => /home/src/readm.txt
license => /usr/src/license.html
IGD2.H => /home/src/igd2.h

strings:
variables => BUILDID,MAJOR

您可以使用Config::IniFiles的方法进行数据访问,而不是使用绑定哈希:

use strict;
use warnings;
use Config::IniFiles;

my $cfg = Config::IniFiles->new( -file => 'File.txt' );

my @sections = $cfg->Sections;

for my $section (@sections) {
    print $section, "\n";
    my @parms = $cfg->Parameters($section);
    for my $param (@parms) {
        print "$param => ", $cfg->val( $section, $param ), "\n";
    }

    print "\n";
}

输出:

strings
variables => BUILDID,MAJOR

BUILDID
VALUE => 898
VERSION.H => /home/src/gd_version.h
readme => /home/src/readm.txt

MAJOR
VALUE => 8
IGD2.H => /home/src/igd2.h
readme => /home/src/readm.txt
license => /usr/src/license.html

答案 1 :(得分:1)

如果解析该配置不是您的中心任务,请考虑使用CPAN中的模块。 Config::IniConfig::Simple而不是重新发明那个特定的轮子。

如果您仍想自己进行解析,您需要识别三种行:

  1. 可以通过类似于^\s*\[(.*)\]\S*$
  2. 的正则表达式描述的部分
  3. 可以由类似于^\s*(.*?)\s*=\s*(.*?)\s*$
  4. 的正则表达式描述的声明
  5. 其他一切。
  6. (严格来说,你会想要使用与.不同的字符类来表示节名,键,值。)

    以下是我的想法:

    my $section;
    while (<STDIN>) {
        chomp;
        if (/^\s*\[(.*)\]\S*$/) {
            $section = $1;
            next;
        } elsif (/^\s*(.*?)\s*=\s*(.*?)\s*$/) {
            my ($key, $value) = ($1, $2);
            say "--- $section . $key = $value";
        } else {
            # invalid
            next;
        }
    }
    

答案 2 :(得分:0)

查看this program第328到371行。这是我解析Windows INI格式的文件。

SECTION_LINEPARAMTER_LINE是在第14行和第15行定义的常量。我这样做是因为我想确保这个钩子只适用于标准的Perl模块。否则,我也会使用Config::INI来进行解析。如果你真的相信这是你计划的重要部分,那就更是如此。

需要注意的重要一点是我将线条与两个不同的正则表达式进行比较。一个是标题行([...]),一个是参数行(...=....)。我还必须跟踪一个部分的开始和结束时间(如果我得到另一个部分标题行,前一部分结束,或者如果我到达文件末尾),并跟踪哪些参数与哪些部分一致。我使用Perl对象来保存参数及其部分,如果不使用对象,则必须使用复杂的Perl哈希值来跟踪值。

另外不要忘记错误跟踪。仔细查看我的代码,然后意识到使用Config::INI为您处理此任务要容易得多。

正如我所说,我没有使用像Config::INI之类的东西的唯一原因是我必须确保我的代码只使用标准的Perl模块。此代码在用户无法控制的系统上运行,在这种情况下添加可选的CPAN Perl模块非常困难。您通常必须提出请求,等待它被填满,并且在许多情况下,依赖于不知道如何执行此操作的人。