Reputation: 377
I have a file that looks like:
1
3
7
8
It has numbers that increase but not in a consistent way: it is random.
I would like a file that looks like:
1 1
2 0
3 1
4 0
5 0
6 0
7 1
8 1
It fills in the missing numbers in the left hand column and adds a \t1
to show that it was present in the original file (0 for absent). So far I have:
#! /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
It isn't producing the desired result. Any ideas?
Upvotes: 2
Views: 1208
Reputation: 126722
This Perl program will do as you ask. It reads each number from the input file and prints a line with a zero for every value preceding it that hasn't been output. It then prints the input value with a one and goes to read the next number from the input
This program expects the path to the input file as a parameter on the command line and prints the output to 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
Upvotes: 4
Reputation: 6626
You are iterating over the lines of your input file, and each time printing one line, so your output only has as much lines as your input.
Instead, you want to keep a counter (like you did), and for each line, while that counter is less that the number on the line, print $counter 0
, because that number is not present in your input:
#! /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;
Also, note that I've use a 3 arguments open, and a lexical variable $in
for your filehandle instead of your IN
, and I've included $!
in the error message so if something goes wrong, you'll know what it was.
Upvotes: 6
Reputation: 54323
One way to do this is to add a second loop that keeps counting up until you have a match.
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
This makes use of the infinite loop while () { ... }
construct, as well as a label (LINE:
) on the outer loop and the next LABEL
keyword, which breaks out of the inner loop and skips to the next iteration of the loop with the label. Since we're counting after comparing, we need to start with 1
.
Upvotes: 2