在 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
我发现类似的问题有不同的解决方案;他们中的一些人使用行号,但我的行号不是恒定的。另一种解决方案使用了“..”,我试过了,但我认为我没有正确应用它。
任何帮助将不胜感激!
下面的程序将按您的要求执行。它是 essential 到 use strict
和 use 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';
}
}
我需要打开一个非常混乱的 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
我发现类似的问题有不同的解决方案;他们中的一些人使用行号,但我的行号不是恒定的。另一种解决方案使用了“..”,我试过了,但我认为我没有正确应用它。
任何帮助将不胜感激!
下面的程序将按您的要求执行。它是 essential 到 use strict
和 use 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';
}
}