在 Perl 中解析 INI 文件并将其转换为哈希的最佳方法是什么?
7 回答
我更喜欢使用Config::IniFiles模块。
如果您更喜欢 perlish 风格,请尝试Tie::Cfg
。样本:
tie my %conf, 'Tie::Cfg', READ => "/etc/connect.cfg";
$conf{test}="this is a test";
最好的方法是按照其他人的建议使用 CPAN 中的可用模块。下面只是为了你自己的理解,假设你有这样的ini文件:
$ more test.ini
[Section1]
s1tag1=s1value1 # some comments
[Section2]
s2tag1=s2value1 # some comments
s2tag2=s2value2
[Section3]
s3tag1=s3value1
您可以只使用 Perl 的正则表达式(或字符串方法)+ 像哈希这样的数据结构来进行自己的不带模块的解析。
示例代码:
$ini="test.ini";
open (INI, "$ini") || die "Can't open $ini: $!\n";
while (<INI>) {
chomp;
if (/^\s*\[(\w+)\].*/) {
$section = $1;
}
if (/^\W*(\w+)=?(\w+)\W*(#.*)?$/) {
$keyword = $1;
$value = $2 ;
# put them into hash
$hash{$section} = [ $keyword, $value];
}
}
close (INI);
while( my( $k, $v ) = each( %hash ) ) {
print "$k => " . $hash{$k}->[0]."\n";
print "$k => " . $hash{$k}->[1]."\n";
}
输出
$ perl perl.pl
Section1 => s1tag1
Section1 => s1value1
Section3 => s3tag1
Section3 => s3value1
Section2 => s2tag2
Section2 => s2value2
Config::Tiny使用起来非常简单直接。
$Config = Config::Tiny->read( 'file.conf' );
my $one = $Config->{section}->{one};
my $Foo = $Config->{section}->{Foo};
从 CPAN 尝试这个模块:Config::INI::Reader
ini文件编辑的读写功能:
sub iniRead
{
my $ini = $_[0];
my $conf;
open (INI, "$ini") || die "Can't open $ini: $!\n";
while (<INI>) {
chomp;
if (/^\s*\[\s*(.+?)\s*\]\s*$/) {
$section = $1;
}
if ( /^\s*([^=]+?)\s*=\s*(.*?)\s*$/ ) {
$conf->{$section}->{$1} = $2;
}
}
close (INI);
return $conf;
}
sub iniWrite
{
my $ini = $_[0];
my $conf = $_[1];
my $contents = '';
foreach my $section ( sort { (($b eq '_') <=> ($a eq '_')) || ($a cmp $b) } keys %$conf ) {
my $block = $conf->{$section};
$contents .= "\n" if length $contents;
$contents .= "[$section]\n" unless $section eq '_';
foreach my $property ( sort keys %$block ) {
$contents .= "$property=$block->{$property}\n";
}
}
open( CONF,"> $ini" ) or print("not open the file");
print CONF $contents;
close CONF;
}
示例用法:
读取conf文件并保存到hash
$conf = iniRead("/etc/samba/smb.conf");
更改您的配置属性或添加新的配置属性
编辑
$conf->{"global"}->{"workgroup"} = "WORKGROUP";
添加了新配置
$conf->{"www"}->{"path"}="/var/www/html";
将新配置保存到文件
iniWrite("/etc/samba/smb.conf",$conf);
对上面的挑剔:
从 CPAN 下载的 Tie::Cfg 不处理其中可能包含空格的部分和键。在为部分和部分内的键设置哈希条目时,需要通过在“键”周围添加引号(“)来更改它。我试图读取的文件是由 MS Windows 的人生成的,因此有很多空间可以走动。
Config::Tiny、Config::IniFiles 对格式很挑剔。如果任何一行不是 [section] 或 key=val 的形式,它们就会抛出错误,并且无法访问散列,至少在 Config::Files 中,无论如何都正确填写了散列。有一个忽略错误选项会很好。我正在尝试读取的文件中有一些虚假的 M4 行,我可以通过 m4 运行以摆脱这些行,但这在我试图用这个特定脚本执行的操作中不是必需的。