如何使用Perl从文件中读取多行值

时间:2012-10-09 12:19:17

标签: perl

我有一个属性文件,比如说

##
## Start of property1
##
##
Property1=\
a:b,\
a1:b1,\
a2,b2
##
## Start of propert2
##
Property2=\
c:d,\
c1:d1,\
c2,d2

请注意,任何给定属性的值可以分为多行。

我想使用Perl读取此属性文件。这在Java中运行良好,因为Java使用反斜杠支持多行值,但在Perl中它是一场噩梦。

在上面的属性文件中,有两个属性 - Property1Property2 - 每个属性都与一个字符串相关联,我可以根据分隔符,: <进行拆分/ p>

对于给定的属性(比如Property1)和给定的列(比如a1),我需要返回第二列(此处b1

代码应该能够忽略注释,空格等。

先谢谢

2 个答案:

答案 0 :(得分:5)

大多数文本处理 - 包括处理反斜杠延续行 - 在Perl中非常简单。你需要的就是这样的读取循环。

while (<>) {
  $_ .= <> while s/\\\n// and not eof;
}

以下程序可以满足我的需求。我在读取循环中调用print来显示已经在连续行上聚合的完整记录。我还演示了提取您提供的b1字段作为示例,并显示了Data::Dump的输出,以便您可以看到创建的数据结构。

use strict;
use warnings;

my %data;

while (<DATA>) {
  next if /^#/;
  $_ .= <DATA> while s/\\\n// and not eof;
  print;
  chomp;
  my ($key, $values) = split /=/;
  my @values = map [ split /:/ ], split /,/, $values;
  $data{$key} = \@values;
}

print $data{Property1}[1][1], "\n\n";

use Data::Dump;
dd \%data;


__DATA__
##
## Start of property1
##
##
Property1=\
a:b,\
a1:b1,\
a2,b2
##
## Start of propert2
##
Property2=\
c:d,\
c1:d1,\
c2,d2

<强>输出

Property1=a:b,a1:b1,a2,b2
Property2=c:d,c1:d1,c2,d2
b1

{
  Property1 => [["a", "b"], ["a1", "b1"], ["a2"], ["b2"]],
  Property2 => [["c", "d"], ["c1", "d1"], ["c2"], ["d2"]],
}

<强>更新

我再次阅读了您的问题,我认为您可能更喜欢不同的数据表示形式。此变体将proerty值保留为哈希值而不是数组数组,否则其行为相同

use strict;
use warnings;

my %data;

while (<DATA>) {
  next if /^#/;
  $_ .= <DATA> while s/\\\n// and not eof;
  print;
  chomp;
  my ($key, $values) = split /=/;
  my %values = map { my @kv = split /:/; @kv[0,1] } split /,/, $values;
  $data{$key} = \%values;
}

print $data{Property1}{a1}, "\n\n";

use Data::Dump;
dd \%data;

<强>输出

Property1=a:b,a1:b1,a2,b2
Property2=c:d,c1:d1,c2,d2
b1

{
  Property1 => { a => "b", a1 => "b1", a2 => undef, b2 => undef },
  Property2 => { c => "d", c1 => "d1", c2 => undef, d2 => undef },
}

答案 1 :(得分:0)

假设您的文件不是太大,这是一个简单的方法:

use strict;
use warnings;

open FILE, "my_file.txt" or die "Can't open file!";

{
    local $/;
    my $file = <FILE>;
    #If \ is found at the end of the line, delete the following line break.
    $file =~ s/\\\n//gs;
}

如果某行以\结尾,则会删除以下换行符。这会将每个多行属性放在一行上。

缺点是这会将整个文件读入内存;如果您的输入文件非常大,您可以将其调整为逐行遍历文件的算法。