【问题标题】:How to read multi-line values from a file using Perl如何使用 Perl 从文件中读取多行值
【发布时间】:2012-10-09 12:19:17
【问题描述】:

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

##
## 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 - 每个都与我可以根据分隔符 ,: 拆分的字符串相关联

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

代码应该可以忽略cmets、空格等

提前致谢

【问题讨论】:

    标签: perl


    【解决方案1】:

    大多数文本处理——包括处理反斜杠续行——在 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"]],
    }
    

    更新

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

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

    【讨论】:

    • 嗨..感谢您的帮助...但还有一个问题我无法弄清楚..在上面的示例中...如果我说 $propName 从最后的第 4 行=“属性1”;打印 $data{$propName}{a1}, "\n\n";它工作正常....但是有一些变量说 $propName 会在适当的时候改变.. print $data{$propName}{a1}, "\n\n";它不打印任何内容...我尝试在此打印语句之前打印 $propName 名称...它在那里打印...但是此打印语句不打印任何内容...类似于此 print $propName print $data {$propName}{a1}, "\n\n";请帮帮我
    【解决方案2】:

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

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

    只要一行以\ 结尾,就会删除以下换行符。这会将每个多行属性放在一行中。

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

    【讨论】:

    • 有什么特别的理由不赞成这个答案吗?
    猜你喜欢
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多