我的问题是我无法弄清楚为什么我的代码将文件中的每一行作为数组的一个元素而不是将整个记录从AD开始作为数组的一个元素。正如您所看到的,我的文件从AD开始到SS结束,对于数据中的所有后续行都是相同的。但我想让阵列中的元素从AD到SS开始,这些元素将包含AD到SS之间的所有行,即BC ....,EG ....,FA ......等等。作为元素的行。我尝试了我的方式并获得相同的文件。任何人都可以检查我的代码。提前谢谢。
AD uuu23
BC jjj
EG iii
FA vvv
SS
AD hhh25
BC kkk
EG ppp
FA aaa
SS
AD ttt26
BC xxx
FA rrr
SS
#!/usr/bin/env perl
use strict;
use warnings;
my $ifh;
my $line = '';
my @data;
my $ifn = "fac.txt";
open ($ifh, "<$ifn") || die "can't open $ifn";
my $a = "AD ";
my $b = "SS ";
my $_ = " ";
while ($line = <$ifh>)
{
chomp
if ($line =~ m/$a/g); {
$line = $_;
push @data, $line;
while ($line = <$ifh>)
{
$line .= $_;
push @data, $line;
last if
($line =~ m/$b/g);
}
}
push @data, $line; }
print @data;
答案 0 :(得分:2)
如果我理解你的问题,事实是你正在阅读文件的方式:
while ($line = <$ifh>)
本质上是一种逐行的方法。它使用“行终止变量”($/
)的内容来了解分割行的位置。更改此行为的一种简单方法是取消定义$/
:
my $oldTerminator = $/;
undef $/;
....... <your processing here>
$/ = $oldTerminator;
所以,你的文件只有一行,但我不确定你的代码会发生什么。
另一种方法如下(记住我所说的关于你逐行阅读文件的事实):而不是做
`push @data, $line;`
在循环的每次迭代中,只是累积在变量中读取的行
$line .= $_;
(就像你已经做过的那样),只在最后只做一次push
。实际上,第二种方法将更容易适用于您的代码(您只需删除您拥有的两个推送语句并将其放在循环之外)。
答案 1 :(得分:1)
我相信你的部分问题在这里
chomp
if ($line =~ m/$a/g);
应该是
chomp;
if ($line =~ m/$a/g)
否则始终执行if语句。如果这有助于您推进,请更新您的问题
答案 2 :(得分:0)
这是一种完成将记录读入数组的方法,删除了换行符:
<强>代码:强>
use strict;
use warnings;
use autodie;
my @data;
my $record;
my $file = "fac.txt";
open my $fh, '<', $file;
while (<$fh>) {
chomp;
if (/^AD /) { # new record starts
$record = $_;
while (<$fh>) {
chomp;
$record .= $_;
last if /^SS\s*/;
}
push @data, $record;
} else { die "Data outside record: $_" }
}
use Data::Dumper;
print Dumper \@data;
<强>输出:强>
$VAR1 = [
'AD uuu23BC jjjEG iiiFA vvvSS',
'AD hhh25BC kkkEG pppFA aaaSS',
'AD ttt26BC xxxFA rrrSS'
];
这是另一个版本,使用输入记录分隔符$/
:
use strict;
use warnings;
use autodie;
my $file = "fac.txt";
open my $fh, '<', $file;
my @data;
$/ = "\nSS";
while (<$fh>) {
s/\n//g;
push @data, $_;
}
use Data::Dumper;
print Dumper \@data;
使用此数据生成相同的输出。它不关心记录开始字符,只关心结尾,即行开头的SS
。