我想阅读以下格式的配置文件我能够读取块名称,即字符串,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的值和其他文件名和路径分配给变量来验证文件的存在。
答案 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::Ini
或Config::Simple
而不是重新发明那个特定的轮子。
如果您仍想自己进行解析,您需要识别三种行:
^\s*\[(.*)\]\S*$
^\s*(.*?)\s*=\s*(.*?)\s*$
(严格来说,你会想要使用与.
不同的字符类来表示节名,键,值。)
以下是我的想法:
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_LINE
和PARAMTER_LINE
是在第14行和第15行定义的常量。我这样做是因为我想确保这个钩子只适用于标准的Perl模块。否则,我也会使用Config::INI来进行解析。如果你真的相信这是你计划的重要部分,那就更是如此。
需要注意的重要一点是我将线条与两个不同的正则表达式进行比较。一个是标题行([...])
,一个是参数行(...=....
)。我还必须跟踪一个部分的开始和结束时间(如果我得到另一个部分标题行,前一部分结束,或者如果我到达文件末尾),并跟踪哪些参数与哪些部分一致。我使用Perl对象来保存参数及其部分,如果不使用对象,则必须使用复杂的Perl哈希值来跟踪值。
另外不要忘记错误跟踪。仔细查看我的代码,然后意识到使用Config::INI
为您处理此任务要容易得多。
正如我所说,我没有使用像Config::INI
之类的东西的唯一原因是我必须确保我的代码只使用标准的Perl模块。此代码在用户无法控制的系统上运行,在这种情况下添加可选的CPAN Perl模块非常困难。您通常必须提出请求,等待它被填满,并且在许多情况下,依赖于不知道如何执行此操作的人。