【问题标题】:How can I parse just part of a file with Perl?如何使用 Perl 仅解析文件的一部分?
【发布时间】:2010-10-19 06:03:14
【问题描述】:

我是 Perl 的新手,但我听说它非常适合解析文件,所以我想试一试。

我有一个包含以下示例信息的文本文件:

High school is used in some
parts of the world, particularly in
Scotland, North America and Oceania to
describe an institution that provides
all or part of secondary education.
The term "high school" originated in
Scotland with the world's oldest being
the Royal High School (Edinburgh) in
1505.

The Royal High School was used as a
model for the first public high school
in the United States, the English High
School founded in Boston,
Massachusetts, in 1821. The precise
stage of schooling provided by a high
school differs from country to
country, and may vary within the same
jurisdiction. In all of New Zealand
and Malaysia along with parts of
Australia and Canada, high school is
synonymous with secondary school, and
encompasses the entire secondary stage
of education.

======================================
Grade1 87.43%
Grade2 84.30%
Grade3 83.00%
=====================================

我想解析文件并且只获取数字信息。我 研究了正则表达式,我想我会使用类似的东西

if (m/^%/) {
    do something
}
else {
    skip the line
}

但是,我真正想做的是跟踪 left 并将数值存储在该变量中。所以,之后 解析文件,我真的很想有以下变量 将 % 值存储在其中。原因是,我想 创建不同等级的饼图/条形图。

1 级 = 87.43 2 级 = 84.30

...

您能建议我应该研究的方法吗?

【问题讨论】:

  • 大家好 - 感谢您的回复。但是,我必须承认我犯了一个错误,我提到它说 Grade1 - 80 % Grade2 - 80 % 等等。问题是您的解决方案使用“Grade”作为正则表达式中的选择标准。但是,这只是一个文件。我的大多数其他文件中都有单独的名称,例如:Mike 80% Shawn 60% Jason 44% 所以现在使用过滤器变得更加棘手......

标签: perl


【解决方案1】:

你需要一个正则表达式。像下面这样的东西应该可以工作

while (<>) {
  /(Grade[0-9]+)\s*([0-9]+\.[0-9]+)/;
  $op{$1} = $2;
}

作为过滤器。 op 哈希将存储年级名称和分数。这比自动实例化变量更可取。

【讨论】:

  • 我的正则表达式中有错字。我现在已经修好了。
【解决方案2】:

如果您可以保证您的兴趣点嵌套在两个=s 之间(并且在给定文件中这些分界线没有奇数),那么触发器运算符在这里很方便:

use strict;    # These two pragmas go a long, ...
use warnings;  # ... long way in helping you code better

my %scores;    # Create a hash of scores

while (<>) {   # The diamond operator processes all files ...
               # ... supplied at command-line, line-by-line

    next unless /^=+$/ .. /^=+$/;  # The flip-flop operator used ...
                                   # ... to filter out only 'grades'

    my ( $name, $grade ) = split;  # This usage of split will break ...
                                   # ... the current line into an array    

    $scores{$name} = $grade;       # Associate grade with name
}

【讨论】:

    【解决方案3】:

    您想使用哈希。像这样的东西应该可以解决问题:

    my %grades = (); # this is a hash
    open(my $fh, "grade_file.txt" ) or die $!;
    while( my $line = <$fh> ) {
         if( my( $name, $grade ) = $line =~ /^(Grade\d+)\s(\d+\.\d+\%) ) {
             $grades{$name} = $grade;
         }
    }
    close($fh);
    

    然后,您的 %grades 哈希将包含姓名和成绩对。 (访问它就像my $value = $grades{'Grade1'}

    也只是一个注释。该语言称为“Perl”,而不是“PERL”。 Perl 社区中的许多人对此感到不满 :-)

    【讨论】:

    • 大家好 - 感谢您的回复。但是,我必须承认我犯了一个错误,我提到它说 Grade1 - 80 % Grade2 - 80 % 等等。问题是您的解决方案使用“Grade”作为正则表达式中的选择标准。但是,这只是一个文件。我的大多数其他文件中都有单独的名称,例如:Mike 80% Shawn 60% Jason 44% 所以它让我
    • 另外,感谢您让我了解 Perl!我不会再犯第二次错误了;)。
    【解决方案4】:

    请参阅Zaid's answer 以获取使用触发器运算符的示例(这是我推荐的)。但是,如果您遇到困难(有时 DWIMmery 可能会妨碍您),您还可以在逐行读取文件时显式维护状态:

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    my %grades;
    my $interesting;
    
    while ( my $line = <DATA> ) {
        if ( not $interesting and $line =~ /^=+\s*\z/ ) {
            $interesting = 1;
            next;
        }
        if ( $interesting ) {
            if ( $line =~ /^=+\s*$/ ) {
                $interesting = 0;
                next;
            }
            elsif ( my ($name, $grade) = $line =~ /^(\w+)\s+(\d+\.\d+%)/ ) {
                # Keep an array in case the same name occurs
                # multiple times
                push @{ $grades{$name} }, $grade;
            }
        }
    }
    
    use YAML;
    print Dump \%grades;
    

    【讨论】:

      【解决方案5】:

      创建动态变量名可能对您生成图表没有多大帮助;使用数组几乎可以肯定是一个更好的主意。

      但是,如果你真的想这样做:

      while (my $line = <$your_infile_handler>){
         if ($line =~ m/(.*) = ([0-9.]*)){
            $$1 = $2;
         }
      }
      

      应该做到这一点。

      【讨论】:

      • 嗨,wooble,你是对的。我一直在查看一些脚本,这些脚本可以从 GD 之类的数据生成图形:(ibm.com/developerworks/library/os-perlgdchart),它们确实提到了创建一个数组,例如 Data [] []。但我不完全确定如何通过解析文件来填充该数组。我将对此进行一些尝试,并在遇到困难时回帖...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      • 2018-12-20
      • 1970-01-01
      相关资源
      最近更新 更多