1

使用しているテキストファイルから行を削除するための次のコードがあります。ただし、実際には必要な行を削除しているわけではありません。ここで多くのテストを行い、行番号を正しく取得すると行が削除されることを確認しました。ただし、$.実際の行番号が重複しているようです(印刷すると、実際の行数は2倍になると表示されます)。

#!/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;

ps-これを使用できることはわかっていますが、この場合、「Tie::File」を使用する方がもう少し簡単だと思いました。

4

1 に答える 1

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);
}

それも機能しないことを除いて。スプライスするときは、配列全体をシフトするため、そのターンのインデックスを進めてはならず、ループを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倍速くなります。

于 2013-02-12T20:35:47.850 に答える