如何从 Perl 访问 INI 文件?

发布于 2024-08-17 16:23:31 字数 41 浏览 3 评论 0原文

在 Perl 中解析 INI 文件并将其转换为哈希的最佳方法是什么?

What is the best way to parse INI file in Perl and convert it to hash?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

蓝色星空 2024-08-24 16:23:31

我更喜欢使用 Config::IniFiles 模块。

I prefer to use Config::IniFiles module.

天冷不及心凉 2024-08-24 16:23:31

如果您喜欢更perlish风格,请尝试 Tie::Cfg。样本:

tie my %conf, 'Tie::Cfg', READ => "/etc/connect.cfg";

$conf{test}="this is a test";

If you like more perlish style then try Tie::Cfg. Sample:

tie my %conf, 'Tie::Cfg', READ => "/etc/connect.cfg";

$conf{test}="this is a test";
兔小萌 2024-08-24 16:23:31

最好的方法是按照其他人的建议使用 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

The best way is to make use of available modules in CPAN as what others have suggested. Below is just for your own understanding, let's say you have ini file like this:

$ more test.ini
[Section1]
    s1tag1=s1value1             # some comments
[Section2]
    s2tag1=s2value1           # some comments
    s2tag2=s2value2
[Section3]
    s3tag1=s3value1

you can do your own parsing w/o modules by using just Perl's regex (or string methods) + data structures like hashes.

Sample Code:

   $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";
    }

output

$ perl perl.pl
Section1 => s1tag1
Section1 => s1value1
Section3 => s3tag1
Section3 => s3value1
Section2 => s2tag2
Section2 => s2value2
魔法唧唧 2024-08-24 16:23:31

Config::Tiny 非常简单易用。

$Config = Config::Tiny->read( 'file.conf' );

my $one = $Config->{section}->{one};
my $Foo = $Config->{section}->{Foo};

Config::Tiny is very easy and straightforward to use.

$Config = Config::Tiny->read( 'file.conf' );

my $one = $Config->{section}->{one};
my $Foo = $Config->{section}->{Foo};
月依秋水 2024-08-24 16:23:31

尝试来自 CPAN 的此模块: Config::INI::Reader

Try this module from CPAN: Config::INI::Reader

手心的海 2024-08-24 16:23:31

对上面的挑剔:

从 CPAN 下载的 Tie::Cfg 不处理可能包含空格的部分和键。当设置该部分和部分内的键的哈希条目时,需要通过在“键”周围添加引号(“)来更改它。我试图读取的文件是由 MS Windows 的人员生成的,因此 Config::Tiny、Config::IniFiles 对格式非常

挑剔,如果任何行不是 [section] 或 key=val 的形式,它们就会抛出错误并且无法访问。至少在 Config::Files 中,哈希值被正确填充,如果我尝试读取的文件中有一些虚假的 M4 行,我可以运行它。通过 m4 来摆脱,但这在我尝试使用这个特定脚本执行的操作中是不必要的。

Nitpicking on the above:

Tie::Cfg, as downloaded from CPAN, does not handle sections and keys that may have spaces in them. It needs to be changed by adding quotes (") around the "keys" when setting the hash entries for both the section and the keys within the sections. The files I'm trying to read were generated by MS Windows' folks, and thus have plenty of spaces to go around.

Config::Tiny, Config::IniFiles are fussy about the format. If any line is not of the form [section] or key=val, they throw an error and one can't get to the hashes, which, at least in Config::Files, are filled in properly anyway. It would be nice to have an ignore error option. The files I'm trying to read have some spurious M4 lines in it, that I could run through m4 to get rid of, but that is not necessary in what I'm trying to do with this particular script.

临走之时 2024-08-24 16:23:31

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 文件并保存到散列

$conf = iniRead("/etc/samba/smb.conf");

更改您的配置属性或添加新的配置属性

编辑

$conf->{"global"}->{"workgroup"} = "WORKGROUP";

添加的新配置

$conf->{"www"}->{"path"}="/var/www/html";

将您的新配置保存到文件

iniWrite("/etc/samba/smb.conf",$conf);

reading and write function for ini file edit:

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

sample usage:

read conf file and saved to hash

$conf = iniRead("/etc/samba/smb.conf");

change the your config attribute or added new config attributes

edit

$conf->{"global"}->{"workgroup"} = "WORKGROUP";

added new config

$conf->{"www"}->{"path"}="/var/www/html";

saved your new configuration to file

iniWrite("/etc/samba/smb.conf",$conf);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文