我有以下代码从我正在使用的文本文件中删除行。但是,它实际上并没有删除我想要的行。我在这里做了很多测试,并确认如果我得到正确的行号,它将删除行。但是,$.
似乎重复了实际的行号(就像我在它上面打印时一样,它表示实际上有两倍的行数!)
#!/usr/bin/perl
# find_company_codes.pl
use strict;
use warnings;
use diagnostics;
use Tie::File;
my $split_file = "//server/folder/splits_table.txt";
# remove fields where only MAS has rollcall
my @file;
my @lines;
tie @file, 'Tie::File', $split_file or die $_;
foreach (@file) {
@lines = split(",",$_);
next if $lines[0] eq "ESDB Link Processing Reg-Prd-CCD";
next if $lines[2] ne "";
next if $lines[3] ne "";
next if $lines[4] ne "";
next if $lines[5] ne "";
next if $lines[6] ne "";
splice(@file, $.,1);
}
untie @file;
P.S。 - 我知道我可以使用this,但是,在这种情况下,我认为使用'Tie :: File`会更加直截了当。
答案 0 :(得分:2)
你不是从文件中读取,而是在迭代数组。 $.
毫无意义。首先,我们需要切换到索引。
for (0..$#file) {
my @fields = split(/,/, $file[$_]);
next if $fields[0] eq "ESDB Link Processing Reg-Prd-CCD";
next if $fields[2] ne "";
next if $fields[3] ne "";
next if $fields[4] ne "";
next if $fields[5] ne "";
next if $fields[6] ne "";
splice(@file, $_, 1);
}
除此之外也不起作用。当你拼接时,你移动整个数组,所以你不能推进转向的索引,你需要尽快完成一个索引的循环。修正:
my $i = 0;
while ($i < $#file) {
my @fields = split(/,/, $file[$i]);
if ( $fields[0] ne "ESDB Link Processing Reg-Prd-CCD"
&& $fields[2] eq ""
&& $fields[3] eq ""
&& $fields[4] eq ""
&& $fields[5] eq ""
&& $fields[6] eq ""
) {
splice(@file, $i, 1);
} else {
++$i;
}
}
好,这有效,但它很疯狂。每个splice
都可以导致文件的其余部分被读取和重写。还有一个不恰当的用法:Tie :: File!以下将会非常快。
use strict;
use warnings;
my $qfn = "//rosefs19w/sal...";
my @file;
{
open(my $fh, '<', $qfn)
or die("Can't open $qfn: $!\n");
@file = <$fh>;
}
my $i = 0;
while ($i < $#file) {
my @fields = split(/,/, $file[$i]);
if ( $fields[0] ne "ESDB Link Processing Reg-Prd-CCD"
&& $fields[2] eq ""
&& $fields[3] eq ""
&& $fields[4] eq ""
&& $fields[5] eq ""
&& $fields[6] eq ""
) {
splice(@file, $i, 1);
} else {
++$i;
}
}
{
open(my $fh, '>', $qfn)
or die("Can't create $qfn: $!\n");
print $fh @file;
}
没错。添加3行额外代码并删除2,代码变为100,1000,10000倍!