在 Perl 中,如何从给定的字符串开始处理文件?

In Perl, how can I start processing a file starting from a given string?

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

(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)),而后面的部分'Information 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

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

任何帮助将不胜感激!

下面的程序将按您的要求执行。它是 essentialuse strictuse warnings 'all' 在你写的每个 Perl 程序的顶部,并用 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 = ;
        next;
    }

    print if $part eq 'A';
}

输出

Name
one
two
three
four
five
Total

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

#!/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  and  eq 'Total';
    }
}