【问题标题】:In Perl, how can I start processing a file starting from a given string?在 Perl 中,如何开始处理从给定字符串开始的文件?
【发布时间】:2016-07-25 16:45:19
【问题描述】:

我需要打开一个非常混乱的 csv 文件(我所说的混乱是指数据之间的空白列和行,我只需要来自某些列的数据)并且只有在到达给定行时才开始将数据分配给列单词“Information A”或“Informasie A”(文件使用两种不同语言中的一种,但格式相同)。该表的格式大致如下:

(n) Name
(n) General info
(n) ID
(n) Contact
(n) General
(n)
(a) Information A
(a)
(a) Name
(a) one
(a) two
(a) three
(a)
(a) four
(a) five
(a) Total
(b) Information B
(b)
(b) Name

程序的基本大纲是为我编写的,它最初在额外细节的第一部分由 $part='n' 指定(如上面的 (n) 所示),而在“信息 A”之后被指定为“a”等等。但是,我想我可能已经删除了一些使整个提取无法使用的代码。我尝试修复它,但这样做弊大于利,因此我尝试从头开始修复它,并希望在此过程中学习一种更简单的方法。

我目前的代码如下:

open (IN_F, "$file") or die "Can't open $file";

  my %file;

while (<IN_F>){

  my $line = $_;
     $line =~ s/\s*$//g;
     $line =~ s/\-//g;

  my $part='n';
     $part='a' if (substr($line,0,13) eq 'Information A');
     $part='b' if (substr($line,0,13) eq 'Information B');

  next if $part='a';
  last if substr($line,0,20) eq 'Litter Information B';

  print "$line\n";
}
exit;

我想要打印的位置:

Name
one
two
three
four
five
Total

我发现类似的问题有不同的解决方案;其中一些使用了行号,但我的不是恒定的。使用了不同的解决方案“..”,我尝试过,但我认为我没有正确应用它。

任何帮助将不胜感激!

【问题讨论】:

    标签: perl loops csv if-statement next


    【解决方案1】:

    下面的程序将按照您的要求进行。在您编写的每个 Perl 程序的顶部,use strictuse warnings 'all'必不可少,并使用 my 声明变量

    use strict;
    use warnings 'all';
    
    my $file = 'information.txt';
    
    open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
    
    my $part = 'n';
    
    while  ( <$fh> ) {
    
        if ( /(?:Information|Informasie) ([A-Z])/ ) {
            $part = $1;
            next;
        }
    
        print if $part eq 'A';
    }
    

    输出

    Name
    one
    two
    three
    four
    five
    Total
    

    【讨论】:

    • 谢谢!我要看看这是否有效。我实际上确实有使用严格和使用警告,只是忘了添加它。为我做程序大纲的人没有添加这些,当我遇到它们并看到它们非常重要后,我添加了它们,显然花了一天时间谷歌搜索并清理所有警告!
    • 在不同的注释.. 是否有一个很好的网页或参考来解释您使用的所有命令?很高兴知道该做什么,但我也想了解我为什么使用它们以及每件作品的作用!我对 perl 和编程还是很陌生,还有很多东西要学!
    • @DKru:“解释所有命令的网页或参考” 这是一个非常广泛的要求。您应该习惯于使用与 Perl 一起安装的 perldoc 命令。或者您可以使用perldoc.perl.org 网站。
    【解决方案2】:

    您需要做的是通读文件,直到看到要开始打印的行并打印到要停止的行:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    while (my $line = <DATA>) {
        if ( $line =~ / Information A/ .. $line =~ / Total/ ) {
            print do { $line =~ s/^\(.\)\s+//; $line };
        }
    }
    
    __DATA__
    (n) Name
    (n) General info
    (n) ID
    (n) Contact
    (n) General
    (n)
    (a) Information A
    (a)
    (a) Name
    (a) one
    (a) two
    (a) three
    (a)
    (a) four
    (a) five
    (a) Total
    (b) Information B
    (b)
    (b) Name
    

    从 5.14 开始,您可以使用 s/...//r 代替 do 块。

    另外,如果文件很大,您不想在看到要打印的最后一行后继续阅读。如果是这种情况,您可以使用:

    while (my $line = <DATA>) {
        if ( $line =~ / Information A/ .. $line =~ / (Total)/ ) {
            print $line =~ s/^\(.\)\s+//r;
            last if $1 and $1 eq 'Total';
        }
    }
    

    【讨论】:

    • 我认为(n)(a)(b)是作者的注解。检查他们代码中的声明if (substr($line,0,13) eq 'Information A')
    猜你喜欢
    • 2020-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多