在逐行阅读文件时保持计数

时间:2018-05-16 14:50:38

标签: perl

我有一个看起来像的文件:

1
3
7
8

它的数字增加但不是以一致的方式:它是随机的。

我想要一个看起来像的文件:

1   1
2   0
3   1
4   0
5   0 
6   0
7   1
8   1

它填写左侧列中缺少的数字,并添加\t1以显示它存在于原始文件中(0表示缺席)。到目前为止,我有:

#! /usr/bin/perl

use warnings;
use strict;

my $infile = $ARGV[0];

open(IN, $infile) or die ("Could not open file.");

my $counter = 0;

while ( my $line  = <IN> ) {

    chomp $line;

    if ( $counter == $line ) {
        print "$line\t1\n";
        ++$counter;
    }
    else {
        print "$counter\t0\n";
        ++$counter;
    }
}

close (IN);

输出

0   0
1   0
2   0
3   0

它不会产生所需的结果。有什么想法吗?

3 个答案:

答案 0 :(得分:6)

您正在迭代输入文件的行,并且每次打印一行,因此您的输出只有输入的行数。

相反,你想要保留一个计数器(就像你一样),并且对于每一行,当该计数器小于该行上的数字时,打印$counter 0,因为输入中不存在该数字:

#! /usr/bin/perl
use warnings;
use strict;

my $infile = $ARGV[0];

open (my $in, '<', $infile) or die ("Could not open file: $!.");

my $counter = 0;
while ( my $line  = <$in> ) {
    chomp $line;
    while ( ++$counter < $line ) {
        print "$counter\t0\n"
    }
    print "$line\t1\n" # or 'print "$counter\t1\n"', whichever you find clearer
}

close $in;

另请注意,我已使用3个参数打开,并使用词法变量$in作为文件句柄而不是IN,并且我已经包含{{1}在错误信息中,如果出现问题,你就会知道它是什么。

答案 1 :(得分:4)

这个Perl程序会按照您的要求执行。它从输入文件中读取每个数字,并为其前面没有输出的每个值打印一个零。然后它用一个打印输入值,然后从输入

读取下一个数字

该程序期望输入文件的路径作为命令行上的参数并将输出打印到STDOUT

use strict;
use warnings 'all';

my $n = 1;

while ( <> ) {
      my ($f) = split;
      print $n++, "\t0\n" while $n < $f;
      print $n++, "\t1\n";
}

输出

1   1
2   0
3   1
4   0
5   0
6   0
7   1
8   1

答案 2 :(得分:2)

这样做的一种方法是添加第二个循环,在你匹配之前一直计算。

use strict;
use warnings;

my $counter = 1;
LINE: while( my $line  = <DATA>) {
    chomp $line;
    while () {
        if ($counter == $line) {
            print "$counter\t1\n";
            $counter++;
            next LINE;
        }
        else {
            print "$counter\t0\n";
            $counter++;
        }
    }
}

__DATA__
1
3
7
8

这使用了无限循环while () { ... }构造,以及外循环上的标签LINE:)和next LABEL keyword,它们打破了离开内循环并跳转到带有标签的循环的下一次迭代。由于我们在比较后计算,我们需要从1开始。